java多线程Lock关键字、Condition 灰太狼 2022-03-20 09:59 254阅读 0赞 一、Lock关键字相对于传统锁synchronized更加面向对象 1、示例:在多线程情况下,按顺序输出指定字符串 定义一个类专门用于输出字符串 public class ThreadLockDemo { int len = s.length(); for (int i = 0; i < len; i++) { System.out.print(s.charAt(i)); } System.out.println(); } } 多线程访问: public static void main(String[] args) { ThreadLockDemo threadLockDemo = new ThreadLockDemo(); new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 10; i++) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } threadLockDemo.printLetter("liucui"); } } }).start(); new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 10; i++) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } threadLockDemo.printLetter("wuchengfeng"); } } }).start(); } 输出结果: wuchengfenliucuig liucui wuchengfeng wuchengfeng liucui wluiucui chengfeng wuchengfeng liucui wliucuuchengfeng i liucui wuchengfeng wliucui uchengfeng wucliucuihengf eng wluiucui chengfeng 由控制台输出可以看出,printLetter方法在多线程访问下被打断,导致输出混乱,这时候使用lock关键字可以有效的解决这个问题 重新改写ThreadLockDemo public class ThreadLockDemo { Lock lock = new ReentrantLock(); public void printLetter(String s) { //加锁 lock.lock(); try { int len = s.length(); for (int i = 0; i < len; i++) { System.out.print(s.charAt(i)); } System.out.println(); } finally { //锁释放 lock.unlock(); } } } liucui wuchengfeng liucui wuchengfeng liucui wuchengfeng wuchengfeng liucui liucui wuchengfeng liucui wuchengfeng wuchengfeng liucui liucui 二、ReadWriteLock读写锁,共享数据的时候,多个线程只有一个线程可以写数据,多个线程可以读数据 public class ThreadLockDemo { ReadWriteLock readWriteLock=new ReentrantReadWriteLock(); public void readData() { //保证多个线程可以同时读数据 readWriteLock.readLock().lock(); System.out.println(Thread.currentThread().getName()+"------------开始读数据--------------------------"); try { Thread.sleep((long)Math.random()*1000); } catch (Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"------------数据读完了--------------------------"); readWriteLock.readLock().unlock(); } public void writeData() { //保证多个线程同时只有一个线程可以写数据 readWriteLock.writeLock().lock(); System.out.println(Thread.currentThread().getName()+"#############开始写数据#############-"); try { Thread.sleep((long)Math.random()*1000); } catch (Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"#############数据写完了#############"); readWriteLock.writeLock().unlock(); } } 三、Condition替换传统的wait、notify功能 static class ThreadSubMain { private boolean isWait = true; Lock lock = new ReentrantLock(); Condition condition = lock.newCondition(); /// 子线程循环20次 void subExcute(int i) { lock.lock(); while (!isWait) { try { condition.await();//类似this.wait() } catch (Exception e) { e.printStackTrace(); } } for (int j = 0; j < 2; j++) { System.out.println("第" + i + "个,第" + j + "子线程--->" + Thread.currentThread().getName()); } // 当子线程执行两次后,改变标识符,唤醒主线程执行; isWait = false; condition.signal(); lock.unlock(); } /// 主线程循环10次 void mainExcute() { lock.lock(); for (int i = 0; i < 10; i++) { while (isWait) { try { condition.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("第" + i + "个主线程--->" + Thread.currentThread().getName()); } // 当主线程执行一次后,改变标识符,唤醒主子线程 isWait = true; condition.signal();/类似this.notify() } lock.unlock(); } } public static void main(String[] args) { ThreadSubMain threadSubMain = new ThreadSubMain(); new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 10; i++) { threadSubMain.subExcute(i); } } }).start(); threadSubMain.mainExcute(); }
还没有评论,来说两句吧...