遇到的一些多线程案例(1)
题目:使用多线程 将["123","456","789"] 这种字符串数组处理为["147","258","369"]形式输出
1 public String[] formart(String[] numbers) { 2 ExecutorService ex = Executors.newFixedThreadPool(3); 3 int size = numbers.length; 4 String[][] pp = new String[size][ size]; 5 for (int i = 0; i < numbers.length; i++) { 6 int k = i; 7 ex.execute(() -> { 8 System.out.println(Thread.currentThread().getName()+" 开始处理--------"); 9 char[] chars = numbers[k].toCharArray(); 10 for (int j = 0; j < chars.length; j++) { 11 pp[ j % size ][k] = String.valueOf(chars[ j ]); 12 } 13 }); 14 } 15 ex.shutdown(); 16 String[] result = new String[size]; 17 for (int i = 0; i <pp.length ; i++) { 18 StringBuffer sb = new StringBuffer(); 19 for (String s : pp[i]) { 20 sb.append(s); 21 } 22 result[i] = sb.toString(); 23 } 24 return result; 25 }
问题:题目用让四个线程循环有序输出1,2,3,4 这儿有次测试发现如果index不用volatile修饰会卡死,详细说明请看:https://www.cnblogs.com/hetutu-5238/p/12188316.html
1 public class Demo2 { 2 3 public static volatile int index = 0; 4 public static void main(String[] args) { 5 ThreadTest t1 = new ThreadTest("线程1" , 0); 6 ThreadTest t2 = new ThreadTest("线程2" , 1); 7 ThreadTest t3 = new ThreadTest("线程3" , 2); 8 ThreadTest t4 = new ThreadTest("线程4" , 3); 9 t1.start(); 10 t2.start(); 11 t3.start(); 12 t4.start(); 13 14 } 15 static class ThreadTest extends Thread { 16 private int i; 17 public ThreadTest(String name , int i) { 18 super(name); 19 this.i = i; 20 } 21 @Override 22 public void run() { 23 while ( true ) { 24 if ( (index & 3) == i ) { 25 System.out.println(Thread.currentThread().getName() + ":" + (i+1)); 26 index++; 27 } 28 } 29 } 30 31 } 32 33 }
问题:有多个线程,代表的是行使的汽车,写一个红绿灯函数,等红灯亮时把所有的汽车线程都暂停,当绿灯亮时所有线程都启动起来
这儿先贴一个看到的比较好的答案,自己利用AQS实现锁,让所有汽车均可以通过这个锁类来控制通行。引用地址:https://segmentfault.com/q/1010000016621995/a-1020000016628980
这儿实现了tryAcquireShared方法通过判断红绿灯来决定是让其获取锁。这儿注意是实现共享锁方法所以下面的汽车均可以获得这把锁
1 import java.io.BufferedReader; 2 import java.io.IOException; 3 import java.io.InputStreamReader; 4 import java.util.ArrayList; 5 import java.util.Collection; 6 import java.util.List; 7 import java.util.concurrent.locks.AbstractQueuedSynchronizer; 8 9 /** 10 * 交通信号灯实现 11 * 等红灯亮时把所有汽车线程都暂停,当绿灯亮时把所有线程都启动起来 12 * @author ccr at 20181008 13 */ 14 public class TrafficLightLatch { 15 private final class Sync extends AbstractQueuedSynchronizer { 16 @Override 17 protected int tryAcquireShared(int ignored) { 18 return redLight == 0 ? 1 : -1; 19 } 20 21 @Override 22 protected boolean tryReleaseShared(int arg) { 23 return true; 24 } 25 } 26 27 /** 28 * 信号灯状态,非0代表红灯,0代表绿灯 29 */ 30 volatile private int redLight; 31 32 private Sync sync; 33 34 /** 35 * 初始化 36 * @param redLight 初始红绿灯状态,非0代表红灯,0代表绿灯 37 */ 38 public TrafficLightLatch(int redLight) { 39 this.redLight = redLight; 40 sync = new Sync(); 41 } 42 43 /** 44 * 红灯则等待,绿灯则直接通过 45 * @throws InterruptedException 46 */ 47 public void await() throws InterruptedException { 48 sync.acquireSharedInterruptibly(1); 49 } 50 51 /** 52 * 切换为红灯 53 */ 54 public void switchRed(){ 55 this.redLight = 1; 56 } 57 58 /** 59 * 切换为绿灯 60 */ 61 public void switchGreen() { 62 this.redLight = 0; 63 sync.releaseShared(0); 64 } 65 66 /** 67 * 是否有线程等待 68 */ 69 public boolean hasQueuedThreads() { 70 return sync.hasQueuedThreads(); 71 } 72 73 /** 74 * 等待中的线程 75 * @return Collection 76 */ 77 public Collection<Thread> getQueuedThreads() { 78 return sync.getQueuedThreads(); 79 } 80 81 public String getLightColor() { 82 return redLight == 0 ? "绿灯" : "红灯"; 83 } 84 85 //测试用例 86 public static void main(String[] args) throws IOException, InterruptedException { 87 //初始化交通信号灯为红灯 88 TrafficLightLatch light = new TrafficLightLatch(1); 89 List<Thread> threads = new ArrayList<>(); 90 //10个线程模拟车辆 91 for (int i = 0; i < 10; i++) { 92 Thread thread = new Thread(() -> { 93 while (!Thread.currentThread().isInterrupted()) { 94 //System.out.println(String.format("%s: 信号灯-%s",Thread.currentThread().getName(),light.getLightColor())); 95 try { 96 //绿灯直接通行,红灯阻塞等待 97 light.await(); 98 } catch (InterruptedException e) { 99 //恢复中断 100 Thread.currentThread().interrupt(); 101 } 102 try { 103 Thread.sleep(2000); 104 } catch (InterruptedException e) { 105 //恢复中断 106 Thread.currentThread().interrupt(); 107 } 108 System.out.println(String.format("%s: 信号灯-%s 通行",Thread.currentThread().getName(),light.getLightColor())); 109 } 110 }); 111 threads.add(thread); 112 thread.start(); 113 } 114 115 //等待输入命令切换交通信号灯 116 BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 117 String command; 118 while ((command = reader.readLine()) != null) { 119 if(command.equals("switchRed")) { 120 light.switchRed(); 121 Thread.sleep(1000); 122 System.out.println(String.format("等待线程数:%d",light.getQueuedThreads().size())); 123 } else if(command.equals("switchGreen")) { 124 light.switchGreen(); 125 Thread.sleep(500); 126 System.out.println(String.format("等待线程数:%d",light.getQueuedThreads().size())); 127 } else if (command.equals("stop")){ 128 System.out.println("terminating..."); 129 threads.forEach(Thread::interrupt); 130 break; 131 } 132 } 133 } 134 }
然后是我自己实现的代码
1 public class Demo4 { 2 3 public static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); 4 public static Lock readLock = readWriteLock.readLock(); 5 public static Lock writeLock = readWriteLock.writeLock(); 6 public static void main(String[] args) throws IOException { 7 writeLock.lock(); 8 try { 9 new CartThread("汽车A").start(); 10 new CartThread("汽车B").start(); 11 new CartThread("汽车C").start(); 12 System.out.println("请输入信号灯 red为红灯 green为绿灯"); 13 BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 14 String command; 15 while ((command = reader.readLine()) != null) { 16 if(command.equals("red")) { 17 System.out.println("红灯亮 所有车停止通行"); 18 if(readWriteLock.getWriteHoldCount()==0) 19 writeLock.lock(); 20 }else if(command.equals("green")){ 21 System.out.println("绿灯亮 所有车开始通行"); 22 writeLock.unlock(); 23 } 24 } 25 }finally { 26 writeLock.unlock(); 27 } 28 } 29 static class CartThread extends Thread{ 30 public CartThread(String name) { 31 super(name); 32 } 33 @Override 34 public void run() { 35 while ( true ){ 36 readLock.lock(); 37 System.out.println(Thread.currentThread().getName()+" :绿灯--发车"); 38 try { 39 Thread.sleep(2000); 40 } catch (InterruptedException e) { 41 }finally { 42 readLock.unlock(); 43 } 44 } 45 } 46 } 47 }