0
点赞
收藏
分享

微信扫一扫

多线程编程细节

江南北 2022-04-24 阅读 45
java

Thread类

Thread类实现了Runnable接口,所以Thread类对象也是Runnable对象,同时Thread类也是线程类Runnable r=new Thread();

构造器:

Thread() //一般用于在Thread类中覆盖定义run方法,可以使用匿名内部类的方式进行定义 
Thread(Runnable) //使用最多的情形,run方法是通过Runnable对象提供的 
Thread(String) //创建线程对象的同时设置线程名称 
Thread(Runnable,String)

 //常见的简化写法 
Thread t=new Thread(()->{ 
    System.out.println(Thread.currentThread()); 
}); 
t.start();

Runnable接口

Runnable接口中只定义了一个方法public void run()Runnable对象一般称为可运行对象,一个线程对象运行的就是Runnable对象中的run方法.

public class MyRunnable implements Runnable{ 
    public void run() throws Exception{ //语法报错,因为不允许抛出异常,如果run方法中有可能会有受检型异常,则需要使用try/catch结构进行处理。 
    //没有返回值,如果需要记录处理结果,必须自己编程实现 
    } 
}

//简化写法 
new Thread(()->{ 
    for(int i=0;i<100;i++){ 
        System.out.println("左手。。。。"); 
        try{
            Thread.sleep(100); //这里有一个受检型异常,因为run不允许抛出异常,所以必须使用try/catch进行处理 
         } catch(InterruptedException e){ 
                e.printStackTrace(); 
         } 
     } 
}).start();

Callable接口

继承Thread类或者实现Runnable接口都有一个缺陷:在执行完成后无法获取执行结果。如果需要获取执行结果,就必须通过共享变量或者使用线程之间通信Pipedxxx管道流的方式来实现,这样使用非常的麻烦。引入Callable接口的目的就是获取执行结果。

Callable接口中有一个方法callcall方法要求有返回值,这个返回值可以通过泛型进行约束,并且允许抛出异常。

public class MyCallable implements Callable<Number> { 
    public Number call() throws Exception{ 
        return 100; --- int 
        return 100.0; --- double 
    } //call方法的返回值类型要和Callable接口后面<>中的类型一致。数值型的包装类的父类型就是Number }

//简化写法 
new Thread(new FutureTask<>(()->{ 
    for(int i=0;i<10;i++){ 
        Sytem.out.println("右手。。。。"); 
        Thread.sleep(30);//允许抛出异常 
    }
    return null; //必须有返回值 
})).start();

Future接口 

Future接口对象用于表示一个任务的生命周期,提供了一组方法用于判断是否已经完成或者取消,以及获取任务的执行结果或取消任务。必要时可以通过get()方法获取线程的执行结果,该方法可以阻塞当前线程直到任务结束为止或者超时。

public class Test1 { 
    public static void main(String[] args) throws Exception { 
        Future f = new FutureTask(() -> { 
            for (int i = 0; i < 1000; i++) { 
                System.out.println(Thread.currentThread() + "...start...");             
                Thread.sleep(10); 
                System.out.println(Thread.currentThread() + "...end..."); 
            }
            return 100; 
        }); 
        if(f instanceof Runnable) { 
            new Thread((Runnable)f).start(); 
            int count=0; 
            while(true) { 
                Thread.sleep(20); 
                System.out.println("任务是否被取消:"+f.isCancelled()+"--- "+count);         
                System.out.println("任务是否已经完成:"+f.isDone()); 
                count++; 
                if(count>10) 
                    f.cancel(true); //取消任务的执行 
                if(count>20) 
                    break; 
            } 
        }//如果任务是取消的方式完成的,这里获取返回值出现异常java.util.concurrent.CancellationException。可以通过这个异常判定取消的方式完成的任 务,不是正常结束,如果正常结束会有返回值,哪怕是null 
            System.out.println("获取到的返回止:"+f.get()); 
     }
}

FutureTask类

FutureTask实现了两个接口RunnableFuture,所以它既可以作为Runnable被线程执行,也可以作为Future获取Callable的返回值

FutureTask是一个可取消的异步计算,FutureTask实现了Future接口的基本方法,提供了cancel操作,可以查询是否已经完成,并获取最终的计算结果。结果只能在计算完成后获取,get方法具备阻塞等待的功能,一旦计算完成,那么计算就不能再次启动或者取消。

Callable<Integer> callable =new MyCallable();
FutureTask<Integer> future =new FutureTask<Integer>(Callable);
new Thread(future).start();

 线程池应用实现

ThreadPoolExecutor:

ThreadPoolExecutor是线程池框架的一个核心类,线程池提供了线程对象的复用机制,并对线程进行统一管理

Executors:

Executors是一个用户创建线程池的工具类。

好了,今天的课程就先总结学习到这里吧!我们下次再见!!!

举报

相关推荐

0 条评论