线程与线程的通信机制_线程安全的类有哪些

(1) 2024-08-10 21:12

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说
线程与线程的通信机制_线程安全的类有哪些,希望能够帮助你!!!。

1. 什么是线程间的通信

线程间通信其实就是多个线程在操作同一个资源时,多个线程之间不断切换执行时所发出的信号。例如:需要创建两个线程,一条线程只打印1-26的数字,另一条只打印A-Z的字母,最终打印结果为1A2B3C4D…26Z时,这时就需要使用线程之间的通信来交替完成。

2. 不同实现方式的demo

首先创建一个共用的线程池去管理和运行这两个线程:

public class ThreadPoolTest { // 创建一个定长的线程池 private static final ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2); // 创建一个数字的数组 public static String[] buildNoArr(int max) { String[] noArr = new String[max]; for(int i=0;i<max;i++){ noArr[i] = Integer.toString(i+1); } return noArr; } // 创建一个字母的数组 public static String[] buildCharArr(int max) { String[] charArr = new String[max]; int tmp = 65; for(int i=0;i<max;i++){ charArr[i] = String.valueOf((char)(tmp+i)); } return charArr; } // 提供公用的打印字符的方法 public static void printStr(String... input){ if(input==null) return; for(String each:input){ System.out.print(each); } } // 提交线程的方法 public void run(Runnable r){ fixedThreadPool.submit(r); } // 关闭线程的方法 public void shutdown(){ fixedThreadPool.shutdown(); } } 
  1. 第一种方式使用 synchronized/wait/notify关键字:是使用共享内存的思想,主要利用的是同步机制的原子性,大致意思就是多个线程需要访问同一个共享变量,谁拿到了锁(获得了访问权限),谁就可以执行。再通过Object的wait()方法使当前线程进入阻塞状态,再调用Object的notify()方法时阻塞的线程进入就绪状态。
public class ThreadTest1 { // 创建线程池对象 ThreadPoolTest poolTest = new ThreadPoolTest(); // 创建一个空的集合对象用来存放打印的字符,并用该对象生成一个对象锁 private final List<String> list = new ArrayList<>(); public Runnable newThreadOne() { final String[] noArr = poolTest.buildNoArr(26); return new Runnable() { public void run() { for (int i = 0; i < noArr.length; i++) { synchronized (list) { if (list.size() % 2 == 1) { try { list.wait(); //调用该锁对象的wait()方法,使当前线程进入等待状态,该线程后面的逻辑暂停执行 } catch (InterruptedException e) { e.printStackTrace(); } } poolTest.printStr(noArr[i]); list.add(noArr[i]); list.notify(); //调用该锁对象的notify()方法,此时会唤醒newThreadTwo线程,使newThreadTwo线程进入就绪状态,当newThreadTwo重新获取到cup时,则继续从上次暂停的代码处往下执行 } } } }; } public Runnable newThreadTwo() { final String[] charArr = poolTest.buildCharArr(26); return new Runnable() { public void run() { for (int i = 0; i < charArr.length; i++) { synchronized (list) { if (list.size() % 2 == 0) { try { list.wait(); //调用该锁对象的wait()方法,使当前线程进入等待状态,该线程后面的逻辑暂停执行 } catch (InterruptedException e) { e.printStackTrace(); } } poolTest.printStr(charArr[i]); list.add(charArr[i]); list.notify();//调用该锁对象的notify()方法,此时会唤醒newThreadOne线程,使newThreadOne线程进入就绪状态,当newThreadOne重新获取到cup时,则继续从上次暂停的代码处往下执行 } } } }; } // 测试 public static void main(String args[]) { ThreadTest1 three = new ThreadTest1(); ThreadPoolTest poolTest = new ThreadPoolTest(); poolTest.run(three.newThreadOne()); poolTest.run(three.newThreadTwo()); poolTest.shutdown(); } } 
  1. 第二种方式使用 volatile 关键字:是使用共享内存的思想,主要利用的是同步机制的可见性,大致意思就是多个线程同时监听一个变量,当这个变量发生变化的时候 ,其他线程能够感知并执行相应的业务。
public class ThreadTest2 { static volatile int value = 1; int one = 0; int two = 0; ThreadPoolTest poolTest = new ThreadPoolTest(); public Runnable newThreadOne() { final String[] noArr = poolTest.buildNoArr(26); return new Runnable() { public void run() { while (true) { if (value == 1 && one < noArr.length) { poolTest.printStr(noArr[one]); one++; value = 2; } } } }; } public Runnable newThreadTwo() { final String[] charArr = poolTest.buildCharArr(26); return new Runnable() { public void run() { while (true) { if (value == 2 && two < charArr.length) { poolTest.printStr(charArr[two]); two++; value = 1; } } } }; } public static void main(String args[]) { ThreadTest2 three = new ThreadTest2(); ThreadPoolTest poolTest = new ThreadPoolTest(); poolTest.run(three.newThreadOne()); poolTest.run(three.newThreadTwo()); poolTest.shutdown(); } } 
  1. 第三种方式使用ReentrantLock 结合 Condition,原理类似synchronized/wait/notify。
public class ThreadTest3 { private static volatile int value = 1; private Lock lock = new ReentrantLock(true); private Condition condition = lock.newCondition(); ThreadPoolTest poolTest = new ThreadPoolTest(); public Runnable newThreadOne() { final String[] noArr = poolTest.buildNoArr(26); return new Runnable() { public void run() { for (int i = 0; i < noArr.length; i++) { try { lock.lock(); //newThreadOne线程获取锁 if (value == 2) { condition.await(); // newThreadOne线程进入等待阻塞 } poolTest.printStr(noArr[i]); value = 2; condition.signal(); // 唤醒调用condition.await()进入阻塞的线程 } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); // 手动释放锁 } } } }; } public Runnable newThreadTwo() { final String[] charArr = poolTest.buildCharArr(26); return new Runnable() { public void run() { for (int i = 0; i < charArr.length; i++) { try { lock.lock(); // newThreadTwo线程获取锁 if (value == 1) { condition.await(); // newThreadTwo线程进入等待阻塞 } poolTest.printStr(charArr[i]); value = 1; condition.signal(); // 唤醒调用condition.await()进入阻塞的线程 } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); // 手动释放锁 } } } }; } public static void main(String args[]) { ThreadTest3 three = new ThreadTest3(); ThreadPoolTest poolTest = new ThreadPoolTest(); poolTest.run(three.newThreadOne()); poolTest.run(three.newThreadTwo()); poolTest.shutdown(); } } 
  1. 第四种方式使用AtomicIntger 原子类,其主要原理是对 int 类型的一个封装,提供原子性的访问和更新操作,其原子性操作的实现是基于 CAS(compare-and-swap)技术,确保程序在被多个线程并发访问时可以得到正确的结果。
public class ThreadTest4 { private AtomicInteger value = new AtomicInteger(1); int one = 0; int two = 0; ThreadPoolTest poolTest = new ThreadPoolTest(); public Runnable newThreadOne() { final String[] noArr = poolTest.buildNoArr(26); return new Runnable() { public void run() { while (true) { if (value.get() == 1 && one < noArr.length) { poolTest.printStr(noArr[one]); one++; value.set(2); } } } }; } public Runnable newThreadTwo() { final String[] charArr = poolTest.buildCharArr(26); return new Runnable() { public void run() { while (true) { if (value.get() == 2 && two < charArr.length) { poolTest.printStr(charArr[two]); two++; value.set(1); } } } }; } public static void main(String args[]) { ThreadTest4 three = new ThreadTest4(); ThreadPoolTest poolTest = new ThreadPoolTest(); poolTest.run(three.newThreadOne()); poolTest.run(three.newThreadTwo()); poolTest.shutdown(); } } 

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

上一篇

已是最后文章

下一篇

已是最新文章

发表回复