java多线程一览
Posted 青瓷
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java多线程一览相关的知识,希望对你有一定的参考价值。
- 线程概述:
- 多线程的目的,不是提高程序的执行速度,而是提高程序的使用率(能抢到CPU的可能比较大). 因为线程是CPU调度的基本单位,所以,当一个程序的线程较多的时候就更容易抢到cpu的资源
- 进程:
- 运行中的程序,是系统进行资源分配和调度的独立单位
- 每个进程都有他自己的内存空间和系统资源
- 线程:
- 是进程中的单个顺序控制流,是一条执行路径,是cpu调度的基本单位
- 一个进程如果有多条执行路径,称:多线程
- 一个进程如果只有一条执行路径,称:单线程
- 线程生命周期:
- java中线程概览: [ ps : 图来自郭朝:http://blog.csdn.net/smartbetter/article/details/51335165]
- 继承Thread类 和 实现Runnable:
![](https://image.cha138.com/20210604/9f6243a04c404b639d89abc58f320fc0.jpg)
1 /** 2 *继承Thread类 和 实现Runnable: 3 * 1.后者解决了java单继承的局限性 4 2.后者更适合多个相同的程序代码处理同一个资源的情况,将数据与代码有效分离,体现了java面向对象的思维 5 * 6 *有人说: 7 * 前者是多个线程各自执行各自的任务, 8 * 后者是多个线程处理相同的任务 9 * 10 *一般用后者的人居多,因为更灵活 11 */ 12 13 // 继承Thread类 14 class MyThread extends Thread{ 15 private static Object shareData; // 实现数据共享 16 @Overwrite 17 public void run(){ 18 System.out.println("当前线程是"+Thread.currentThread.getName()); 19 } 20 } 21 // 创建线程 22 class Main{ 23 public static void main(String[] args) { 24 Thread thread=new MyThread(); 25 Thread thread2=new MyThread(); 26 thread.start(); // 线程开启 27 thread2.start(); // 线程开启 28 } 29 }
- 实现Runnable创建线程类:
![](https://image.cha138.com/20210604/9f6243a04c404b639d89abc58f320fc0.jpg)
1 // 实现Runnable创建线程类 2 class MyRunnable implements Runnable{ 3 private Object shareData; // 实现数据共享 4 public void run(){ 5 System.out.println("当前线程是"+Thread.currentThread.getName()); 6 } 7 } 8 //创建线程 9 class Main{ 10 public static void main(String[] args) { 11 // 两个线程将共享shareData共享数据 12 Runnable runa=new MyRunnable(); 13 Thread thread=new MyThread(runa); 14 Thread thread2=new MyThread(runa); 15 thread.start(); // 线程开启 16 thread2.start(); // 线程开启 17 } 18 }
- 使用Callable 和 Future接口:
![](https://image.cha138.com/20210604/9f6243a04c404b639d89abc58f320fc0.jpg)
1 /** 2 * 该代码来源: @蛊惑Into 3 * Callable 和 Future接口 4 * Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其它线程执行的任务。 5 * Callable和Runnable有几点不同: 6 * (1)Callable规定的方法是call(),而Runnable规定的方法是run(). 7 * (2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。 8 * (3)call()方法可抛出异常,而run()方法是不能抛出异常的。 9 * (4)运行Callable任务可拿到一个Future对象, 10 * Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。 11 * 通过Future对象可了解任务执行情况,可取消任务的执行,还可获取任务执行的结果。 12 */ 13 public class CallableAndFuture { 14 15 public static class MyCallable implements Callable{ 16 private int flag = 0; 17 public MyCallable(int flag){ 18 this.flag = flag; 19 } 20 public String call() throws Exception{ 21 if (this.flag == 0){ 22 return "flag = 0"; 23 } 24 if (this.flag == 1){ 25 try { 26 while (true) { 27 System.out.println("looping."); 28 Thread.sleep(2000); 29 } 30 } catch (InterruptedException e) { 31 System.out.println("Interrupted"); 32 } 33 return "false"; 34 } else { 35 throw new Exception("Bad flag value!"); 36 } 37 } 38 } 39 40 public static void main(String[] args) { 41 42 // 定义3个Callable类型的任务 43 MyCallable task1 = new MyCallable(0); 44 MyCallable task2 = new MyCallable(1); 45 MyCallable task3 = new MyCallable(2); 46 47 // 创建一个执行任务的服务 48 ExecutorService es = Executors.newFixedThreadPool(3); 49 try { 50 // 提交并执行任务,任务启动时返回了一个Future对象, 51 52 // 如果想得到任务执行的结果或者是异常可对这个Future对象进行操作 53 Future future1 = es.submit(task1); 54 // 获得第一个任务的结果,如果调用get方法,当前线程会等待任务执行完毕后才往下执行 55 System.out.println("task1: " + future1.get()); 56 57 58 Future future2 = es.submit(task2); 59 // 等待5秒后,再停止第二个任务。因为第二个任务进行的是无限循环 60 Thread.sleep(5000); 61 System.out.println("task2 cancel: " + future2.cancel(true)); 62 63 64 // 获取第三个任务的输出,因为执行第三个任务会引起异常 65 // 所以下面的语句将引起异常的抛出 66 Future future3 = es.submit(task3); 67 System.out.println("task3: " + future3.get()); 68 } catch (Exception e){ 69 System.out.println(e.toString()); 70 } 71 72 // 停止任务执行服务 73 es.shutdownNow(); 74 75 } 76 77 }
- 线程控制:
![](https://image.cha138.com/20210604/9f6243a04c404b639d89abc58f320fc0.jpg)
1 // 线程控制 2 3 join()线程---必须等线程th执行完成后才能继续向下执行 4 ... 5 th.start(); 6 th.join(); 7 ... 8 9 yield()礼让---注意和线程通信中wait()区分,yield将线程放到就绪队列,而wait将其放到阻塞队列 10 ...th.doSomething... 11 th.yield(); 12 ...th.doSomethingElse... 13 14 sleep()睡眠---线程睡眠,将进入阻塞队列 15 ...doSomething... 16 Thread.sleep(1000); 17 ...continueDoSomething... 18 19 setDaemon()后台线程---将线程设置为后台线程,将在前台线程都死亡后自动死亡 20 .... 21 th.setDaemon(true); 22 .... 23 24 setPrority()优先级---设置优先级 25 ... 26 th.setPrority(5); 27 th.start(); 28 ...
- 线程同步的3种实现:
![](https://image.cha138.com/20210604/9f6243a04c404b639d89abc58f320fc0.jpg)
1 /* 线程同步的3种实现: 2 * 1.同步代码块:锁对象可以是任意对象 3 synchronized(obj){同步代码块} 4 * 2.同步方法: 5 2.1 普通同步方法,锁对象是this 6 public synchronized void fun(){...} 7 2.2 静态同步方法,锁对象是.class字节码对象 8 public static synchronized void fun(){...} 9 3.同步锁:javaAPI提供了多种锁,如读写锁等,以及一些工具类的锁(同时具有同步和通讯特点) 10 private Lock lock=new ReentrantLock(); 11 ... 12 lock.lock(); 13 ...doSomething... 14 lock.unLock(); 15 * 16 * 17 *以下着重介绍几种工具类的锁使用: 18 Samaphore 19 CyclicBarrier 20 CountDownLatch 21 */ 22 /** 23 * 线程互斥与通信: 24 * 线程通讯之传统线程通讯: Semaphore信号灯工具 25 * 传统的互斥,是由线程本身来控制锁的占有和释放,这就导致必须当前线程完成,或是主动让出锁,下一个线程才有机会, 26 * 而semaphore工具, 提供相当于专门的锁的管理方全权控制索,任何线程的请求都通过管理方的许可,这样就解放了锁的控制权,让多个线程共享锁 27 * 28 *共有3盏灯,一次来了10个人,只用其中的3个人能够拿到等,当有灯还回的时候,等候队列的人才有机会拿到灯 29 *可用于死锁恢复的一些场景 30 * 31 * @throws Exception 32 * @author ware E-mail: 33 * @version create time: 20172017年3月1日下午11:35:41 34 */ 35 public class ThreadCommunication3 { 36 37 public static void main(String[] args) { 38 final Semaphore sp=new Semaphore(3, true); 39 40 ExecutorService pool = Executors.newCachedThreadPool(); 41 42 for (int i = 0; i < 10; i++) { 43 Runnable task=new Runnable() { 44 @Override 45 public void run() { 46 try { 47 sp.acquire(); // 请求锁 48 } catch (InterruptedException e) { 49 e.printStackTrace(); 50 } 51 System.out.println("线程"+Thread.currentThread().getName()+"已经进入---可用数"+(3-sp.availablePermits())); 52 53 try { 54 Thread.sleep(1000); 55 } catch (InterruptedException e) { 56 e.printStackTrace(); 57 } 58 59 System.out.println("线程"+Thread.currentThread().getName()+"准备离开"); 60 61 sp.release(); //释放锁 62 } 63 }; 64 65 pool.submit(task); 66 } 67 68 } 69 70 71 } 72 73 /** 74 * 线程互斥与通信: 75 * 线程通讯之传统线程通讯: CyclicBarrier工具 76 * 所有规定的线程必须都在完成某一项工作之后才能继续下一项工作 77 * 78 * 如: 班级郊游,只有所有的人都到了集合点(工作1)才能出发(工作2) 79 * 80 * @throws Exception 81 * @author ware E-mail: 82 * @version create time: 20172017年3月1日下午11:35:41 83 */ 84 public class ThreadCommunication4 { 85 86 public static void main(String[] args) { 87 final CyclicBarrier cb=new CyclicBarrier(4); // 约定有多少个人 88 89 ExecutorService pool = Executors.newCachedThreadPool(); 90 91 for (int i = 0; i < 4; i++) { 92 Runnable task=new Runnable() { 93 @Override 94 public void run() { 95 96 try { 97 // 第一阶段工作 98 Thread.sleep((long) (Math.random()*1000)); 99 System.out.println(Thread.currentThread().getName()+"到达集合点,当前共有"+cb.getNumberWaiting()+"人在等待"); 100 cb.await(); 101 102 // 第二阶段工作 103 Thread.sleep((long) (Math.random()*1000)); 104 System.out.println(Thread.currentThread().getName()+"出发中"+cb.getNumberWaiting()+"人出发中"); 105 cb.await(); 106 107 // 第三阶段工作 108 Thread.sleep((long) (Math.random()*1000)); 109 System.out.println(Thread.currentThread().getName()+"到达景点"+cb.getNumberWaiting()+"人到达景点"); 110 cb.await(); 111 112 } catch (Exception e) { 113 e.printStackTrace(); 114 } 115 116 } 117 118 }; 119 120 pool.submit(task); 121 } 122 123 } 124 125 } 126 127 /** 128 * 线程互斥与通信: 129 * 线程通讯之传统线程通讯: CountDownLatch工具 130 * 如同一个倒计时器,当countDown()到0的时候,所有等该"计时器"的线程都会受到消息 131 * 132 * 如: 所有的运动员都在等裁判的命令,裁判一声令下,所有的运动员收到消息开始跑,裁判等到所有的人都跑到终点了才宣布结构 133 * 134 * @throws Exception 135 * @author ware E-mail: 136 * @version create time: 20172017年3月1日下午11:35:41 137 */ 138 public class ThreadCommunication6 { 139 140 public static void main(String[] args) { 141 final CountDownLatch cdOrder=new CountDownLatch(1); // 裁判命令 142 final CountDownLatch cdAnswer=new CountDownLatch(4); // 运动员的消息状态 143 144 ExecutorService pool = Executors.newCachedThreadPool(); 145 146 // 4个运动员 147 for (int i = 0; i < 4; i++) { 148 Runnable task=new Runnable() { 149 @Override 150 public void run() { 151 152 try { 153 System.out.println(Thread.currentThread().getName()+"---已经准备好了,等待命令"); 154 155 cdOrder.await(); // 等命令 156 157 System.out.println("等到命令并开跑"); 158 Thread.sleep((long) (Math.random()*1000)); 159 System.out.println(Thread.currentThread().getName()+"跑完全程了"); 160 161 cdAnswer.countDown(); 162 163 } catch (Exception e) { 164 e.printStackTrace(); 165 } 166 167 } 168 169 }; 170 171 pool.submit(task); 172 } 173 174 175 // 1个裁判 176 Runnable coach=new Runnable() { 177 @Override 178 public Java多线程——Lock&Condition