使用多线程循环交替打印字符
使用Condition + Lock 进行实现
private static int count_print = 1;
(1)此处只能用static,来实现每打印一个字符,下一个字符长度加一,static是使该变量只有一个副本,任何改变都是对这个副本的内容做操作
(2)若是想实现每打印一组,下一组字符每个字符长度加一,就不使用static,因为三个线程,有三个线程实例即ThreadTest实例,若不设置成静态,
那么每次改变的是对象内部的count_print属性,所以其他两个线程是不可见的
程序一:
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class ThreadTest implements Runnable { public static final int COUNT = 5; private final ReentrantLock reentrantLock; private final Condition thisCondition; private final Condition nextCondition; private final char printChar; // 此处只能用static,来实现每打印一个字符,下一个字符长度加一,static是使该变量只有一个副本,任何改变都是对这个副本的内容做操作 // 若是想实现每打印一组,下一组字符每个字符长度加一,就不使用static,因为三个线程,有三个线程实例即ThreadTest实例,若不设置成静态, // 那么每次改变的是对象内部的count_print属性,所以其他两个线程是不可见的 private static int count_print = 1; public ThreadTest(ReentrantLock reentrantLock, Condition thisCondition, Condition nextCondition, char printChar) { this.reentrantLock = reentrantLock; this.thisCondition = thisCondition; this.nextCondition = nextCondition; this.printChar = printChar; } @Override public void run() { reentrantLock.lock(); try { for (int i = 0; i < COUNT; i++) { for (int j = 0; j < count_print; j++) { System.out.print(printChar); } count_print += 1; nextCondition.signal(); // 不是最后一次则通过thisCondtion等待被唤醒 // 必须要加判断,不然虽然能够打印5次,但5次后就会直接死锁 if (i < COUNT - 1) { try { // 使用Condition的await()方法将当前线程放入等待队列,并使其能在下一次被唤醒继续往下执行,而不是从头开始执行 thisCondition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } } } finally { reentrantLock.unlock(); } } public static void main(String args[]) throws InterruptedException { ReentrantLock lock = new ReentrantLock(); Condition conditionA = lock.newCondition(); Condition conditionB = lock.newCondition(); Condition conditionC = lock.newCondition(); Thread threadA = new Thread(new ThreadTest(lock, conditionA, conditionB, 'A')); Thread threadB = new Thread(new ThreadTest(lock, conditionB, conditionC, 'B')); Thread threadC = new Thread(new ThreadTest(lock, conditionC, conditionA, 'C')); threadA.start(); Thread.sleep(100); threadB.start(); Thread.sleep(100); threadC.start(); } }
(1)//此处只能用static,来实现每打印一个字符,下一个字符长度加一,static是使该变量只有一个副本,任何改变都是对这个副本的内容做操作
private static int count_print = 1;
输出结果:
(2)若是想实现每打印一组,下一组字符每个字符长度加一,就不使用static,因为三个线程,有三个线程实例即ThreadTest实例,若不设置成静态,
那么每次改变的是对象内部的count_print属性,所以其他两个线程是不可见的,可能不太好理解,将ThreadTest类单独写出来,在利用import引入进另一个有主方法的类就比较直观了
private int count_print = 1;
输出结果:
程序二
//只是循环打印每组字符,不考虑字符增长 import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class ThreadTest implements Runnable { public static final int COUNT = 5; private final ReentrantLock reentrantLock; private final Condition thisCondition; private final Condition nextCondition; private final char printChar; private static int count_print = 1; public ThreadTest(ReentrantLock reentrantLock, Condition thisCondition, Condition nextCondition, char printChar) { this.reentrantLock = reentrantLock; this.thisCondition = thisCondition; this.nextCondition = nextCondition; this.printChar = printChar; } @Override public void run() { reentrantLock.lock(); try { for (int i = 0; i < COUNT; i++) { System.out.print(printChar); nextCondition.signal(); if (i < COUNT - 1) { try { // 使用Condition的await()方法将当前线程放入等待队列,并使其能在下一次被唤醒继续往下执行,而不是从头开始执行 thisCondition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } } } finally { reentrantLock.unlock(); } } public static void main(String args[]) throws InterruptedException { ReentrantLock lock = new ReentrantLock(); Condition conditionA = lock.newCondition(); Condition conditionB = lock.newCondition(); Condition conditionC = lock.newCondition(); Thread threadA = new Thread(new ThreadTest(lock, conditionA, conditionB, 'A')); Thread threadB = new Thread(new ThreadTest(lock, conditionB, conditionC, 'B')); Thread threadC = new Thread(new ThreadTest(lock, conditionC, conditionA, 'C')); threadA.start(); Thread.sleep(100); threadB.start(); Thread.sleep(100); threadC.start(); } }
运行结果为:
Windy心梦无痕