多线程基础回顾(一)-线程创建

线程创建

1.继承Thread类,重写run()

缺点:无法继承其他类;

2.实现Runable接口,实现run()

优点:

  • 解决了第一种方式的局限性;
  • 适合多个相同的程序代码的线程去处理同一个资源
  • 线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类

3.使用ExecutorService、Callable、Future实现有返回结果的多线程

优点:可返回结果,可抛出异常,可继承其他类; 缺点:步骤相对前者复杂;

 1 //实现Callable接口,实现call();
 2 public class myThread implements Callable<String>{
 3     private String name;
 4     public ThreadTest(String name) {
 5         this.name = name;
 6     }
 7     @Override
 8     public String call() throws Exception {
 9         return name+"==>返回结果";
10     }
11     
12     public static void main(String[] args) {
13         //创建 Callable 实现类的实例,
14         myThread dog = new myThread("小狗");
15         myThread cat = new myThread("小猫");
16         //使用 FutureTask 类来包装 Callable 对象
17         FutureTask<String> task1 = new FutureTask<String>(dog);
18         FutureTask<String> task2 = new FutureTask<String>(cat);
19         //使用 FutureTask 对象作为 Thread 对象的 target 创建并启动新线程
20         Thread thread1 = new Thread(task1,"线程1");
21         Thread thread2 = new Thread(task2,"线程2");
22         thread1.start();
23         thread2.start();
24         try {
25             //调用 FutureTask 对象的 get() 方法来获得子线程执行结束后的返回值
26             System.out.println(task1.get());
27             System.out.println(task2.get());
28         } catch (InterruptedException e) {
29             e.printStackTrace();
30         } catch (ExecutionException e) {
31             e.printStackTrace();
32         }
33     }
34 }
View Code

4.通过线程池方式:

优点:提高线程利用率,减少过多线程创建、销毁的损耗。

 1 public class ThreadTest {
 2     public static void main(String[] args) {
 3         //创建线程池
 4         ExecutorService ser = Executors.newFixedThreadPool(2);
 5         //创建任务
 6         ser1.execute(new Runnable() {
 7                 @Override
 8                 public void run() {
 9                     System.out.println("小鸡");
10                 }
11             });
12             
13         //创建有返回结果的任务(通过Callable实例)
14            Future<String> rs = ser1.submit(new Callable<String>() {
15             @Override
16             public String call() throws Exception {
17                 return "haha";
18             }
19         });
20 
21         try {
22             //get()获取返回结果
23             System.out.println(result1.get());
24         } catch (InterruptedException e) {
25             e.printStackTrace();
26         } catch (ExecutionException e) {
27             e.printStackTrace();
28         }
29         //关闭线程池
30         ser.shutdown();
31         //此时线程未必即刻关闭,若需要等线程池关闭后执行某些逻辑,通过awaitTermination()阻塞等待
32         try {
33                 while(!ser1.awaitTermination(1000, TimeUnit.MILLISECONDS)) {
34                     System.out.println("等待线程池关闭");
35                 }
36                 System.out.println("线程池已关闭");
37             } catch (InterruptedException e) {
38                 e.printStackTrace();
39             }
40         
41     }
42 }
View Code

使用线程池记得最后关闭线程池

  • shutdown():修改状态为SHUTDOWN,interrupt空闲线程,不影响正在运行的线程逻辑,对于新提交的线程抛出rejectedExecution异常。所以使用shutdown()关闭线程,需要确保线程不存在永久阻塞,否则线程池将关闭不了。
  • shundownNow():强制关闭线程,修改状态为STOP,给与线程池内所有工作线程interrupt标志。所以若线程处于阻塞状态,抛出InterruptedException异常,否则执行完线程逻辑。所以使用shundownNow()注意对任务捕捉异常。
  • shutdownNow()和shuwdown()调用完,线程池并不是立马就关闭了。若需要等待线程池关闭后做某些事需要使用awaitTermination()。
  • awaitTermination(long timeout,TimeUnit unit):等待timeout后检测线程池是否关闭,返回结果是线程池是否已停止,返回true表示状态为terminated ,所有线程结束线程池已关闭;返回false,表示超时,线程池未关闭。
posted @ 2019-01-23 16:04  哈比Sport  阅读(131)  评论(0编辑  收藏  举报