本文最后更新于:2022年7月14日 晚上
概览 :Java并发练习
基础知识
函数
作用
其他
isAlive()
判断当前线程是否还存活
join()
等待一个线程死亡
Thread.yield()
使得当前线程放弃执行权
interrupt()
将线程状态标记为中断
isInterrupted()
判断是否被中断
Thread.interrupted()
判断是否被中断,可消除中断标记
三个任务打印1,2,3 如何让输出有序? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class MyTask implements Runnable { private int integer; private Thread thread; public void setInteger (int integer) { this .integer = integer; } public void setThread (Thread thread) { this .thread = thread; } @Override public void run () { if (thread != null ){ try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(integer); } }
主方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class Main { public static void main (String[] args) { MyTask task1 = new MyTask(); MyTask task2 = new MyTask(); MyTask task3 = new MyTask(); Thread t1 = new Thread(task1); Thread t2 = new Thread(task2); Thread t3 = new Thread(task3); task1.setInteger(1 ); task2.setInteger(2 ); task2.setThread(t1); task3.setInteger(3 ); task3.setThread(t2); t1.start(); t2.start(); t3.start(); } }
控制多个任务执行顺序
任务1,2,3 可以并发执行,4在前三个执行完成后执行,然后5,6,7三个任务执行。
任务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class Tasks implements Runnable { private int integer; public Tasks () { } public Tasks (int integer) { this .integer = integer; } public int getInteger () { return integer; } public void setInteger (int integer) { this .integer = integer; } @Override public void run () { try { Thread.sleep(new Random().nextInt(2000 )); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(integer); } }
执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 public class Main { public static void main (String[] args) { ThreadPoolExecutor threadPool = new ThreadPoolExecutor(4 ,8 ,10 , TimeUnit.SECONDS,new LinkedBlockingDeque<>()); Tasks task1 = new Tasks(1 ); Tasks task2 = new Tasks(2 ); Tasks task3 = new Tasks(3 ); Tasks task4 = new Tasks(4 ); Tasks task5 = new Tasks(5 ); Tasks task6 = new Tasks(6 ); Tasks task7 = new Tasks(7 ); threadPool.execute(task1); threadPool.execute(task2); threadPool.execute(task3); threadPool.shutdown(); while (!threadPool.isTerminated()){ } Thread t4 = new Thread(task4); t4.start(); try { t4.join(); } catch (InterruptedException e) { e.printStackTrace(); } threadPool = new ThreadPoolExecutor(4 ,8 ,10 , TimeUnit.SECONDS,new LinkedBlockingDeque<>()); threadPool.execute(task5); threadPool.execute(task6); threadPool.execute(task7); threadPool.shutdown(); while (!threadPool.isTerminated()){ } System.out.println("执行结束" ); } }
疑问?shutdown之后还能重启吗?还是必须要创建一个新的线程池。
生产者与消费者 - Synchornized 自定义数据类
1 2 3 4 5 6 7 8 9 10 11 public class MyData { private String data; public String getData () { return data; } public void setData (String data) { this .data = data; } }
生产者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class Producer implements Runnable { private MyData myData; public Producer (MyData myData) { this .myData = myData; } @Override public void run () { int count = 0 ; while (true ){ synchronized (myData){ if (myData.getData() == null ){ System.out.println("生产数据" + ++count); myData.setData(count+"" ); } myData.notify(); try { myData.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }
消费者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class Consumer implements Runnable { private MyData myData; public Consumer (MyData myData) { this .myData = myData; } @Override public void run () { while (true ){ synchronized (myData){ if (myData.getData() != null ){ System.out.println("消费数据" + myData.getData()); myData.setData(null ); } myData.notify(); try { myData.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }
启动
1 2 3 4 5 6 7 8 9 10 11 12 13 public class Main { public static void main (String[] args) { MyData data = new MyData(); Producer producer = new Producer(data); Consumer consumer = new Consumer(data); Thread t1 = new Thread(producer); Thread t2 = new Thread(consumer); t1.start(); t2.start(); } }
生产者与消费者 - Lock&Condition 数据类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public class Messge { private Lock lock = new ReentrantLock(); private Condition prodCondition = lock.newCondition(); private Condition consCondition = lock.newCondition(); private String message; public void setMessage (String message) throws InterruptedException { lock.lock(); try { while (this .message != null ){ prodCondition.await(); } this .message = message; System.out.println("生产数据: " + this .message); consCondition.signalAll(); }finally { lock.unlock(); } } public String getMessage () throws InterruptedException { lock.lock(); try { while (this .message == null ){ consCondition.await(); } System.out.println("消费数据: " + this .message); prodCondition.signalAll(); return this .message; }finally { this .message = null ; lock.unlock(); } } }
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class Main { public static void main (String[] args) { Messge messge = new Messge(); Thread t1 = new Thread(()->{ for (int i = 0 ;i < 10 ;i++) { try { messge.setMessage("消息" + i); } catch (InterruptedException e) { e.printStackTrace(); } } }); Thread t2 = new Thread(()->{ for (int i = 0 ;i < 10 ;i++) { try { System.out.println(messge.getMessage()); } catch (InterruptedException e) { e.printStackTrace(); } } }); t1.start(); t2.start(); } }
不可重入锁的例子 synchornized以及ReentrantLock都是可重入锁,表示一个锁可以重复使用,那么如何编写一个不可重入的锁呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 public class UnReentrantLock implements Lock { private Thread thread; @Override public void lock () { synchronized (this ){ while (thread != null ){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } thread = Thread.currentThread(); } } @Override public void unlock () { synchronized (this ){ if (thread != Thread.currentThread()){ return ; } thread = null ; notifyAll(); } } @Override public void lockInterruptibly () throws InterruptedException { } @Override public boolean tryLock () { return false ; } @Override public boolean tryLock (long time, TimeUnit unit) throws InterruptedException { return false ; } @Override public Condition newCondition () { return null ; } }
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class Main { public static void main (String[] args) { Lock lock = new UnReentrantLock(); lock.lock(); try { System.out.println("获取锁,执行" ); lock.lock(); try { System.out.println("第二次获取锁,执行" ); }finally { lock.unlock(); } }finally { lock.unlock(); } } }
读写锁实现并发容器 https://www.bilibili.com/video/BV1Z54y1j7JT?p=29