线程打印ABC有关问题
AB线程交替打印1到10
synchronized+notifyAll+wait方式:利用 num++ 进行让AB线程间接访问
public class thread1_100 {
public static int num=1;
private static final Object lock=new Object();
private void print(int target){
if(num>10) {
return ;
}
synchronized (lock){
while(num<=10){
System.out.print(Thread.currentThread().getName()+": ");
System.out.print(num);
num++;
lock.notifyAll();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.notifyAll();//主线程
}
}
public static void main(String[] args) {
thread1_100 thread1_100=new thread1_100();
new Thread(()->{thread1_100.print(num);},"A").start();
new Thread(()->{thread1_100.print(num);},"B").start();
}
}
结果显示:
A:1B:2A:3B:4A:5B:6A:7B:8A:9B:10
AB线程交替打印1到10(2)
synchronized+notifyAll+wait方式:利用奇数和偶数交替打印
public class thread2__1_100 {
public static void main(String[] args) {
thread2__1_100 thread2__1_100=new thread2__1_100();
new Thread(()->{thread2__1_100.printabc(0);},"A").start();
new Thread(()->{thread2__1_100.printabc(1);},"B").start();
}
private static int num=0;
private static final Object lock=new Object();
private void printabc(int targetname) {
while (true) {
synchronized (lock) {
while (num % 2 != targetname) {
if(num>=10){//主线程没有退出
break;
}
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (num >=10) {
break;
}
num++;
System.out.print(Thread.currentThread().getName() + ":" + num);
lock.notifyAll();
}
}
}
}
A:1B:2A:3B:4A:5B:6A:7B:8A:9B:10
前面两种方法的wait()方法和notifyAll()方法位置需要多多思考
多个线程交替打印1-n
第一种
根据前面两个例子可以判断是可以推断出这个题目的思考
如果使用的是第一种方法在最后多加入一个c,我们多运行几次会发现有问题
public class thread1_100 {
public static int num=1;
private static final Object lock=new Object();
private void print(int target){
if(num>10) {
return ;
}
synchronized (lock){
while(num<=10){
System.out.print(Thread.currentThread().getName()+":");
System.out.print(num);
num++;
lock.notifyAll();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.notifyAll();//主线程
}
}
public static void main(String[] args) {
thread1_100 thread1_100=new thread1_100();
new Thread(()->{thread1_100.print(num);},"A").start();
new Thread(()->{thread1_100.print(num);},"B").start();
new Thread(()->{thread1_100.print(num);},"c").start();
}
}
结果:
A:1B:2A:3B:4A:5B:6A:7c:8A:9B:10
A:1B:2A:3B:4A:5B:6A:7c:8B:9c:10
在lock.notifyAll()方法执行后,并不能保证是按照ABC这样的顺序进行排序的。所以会出现不同结果
第二种
根据上述的第二种方法 用%判断
public class thread2__1_100 {
public static void main(String[] args) {
thread2__1_100 thread2__1_100=new thread2__1_100();
new Thread(()->{thread2__1_100.printabc(0);},"A").start();
new Thread(()->{thread2__1_100.printabc(1);},"B").start();
new Thread(()->{thread2__1_100.printabc(2);},"C").start();
}
private static int num=0;
private static final Object lock=new Object();
private void printabc(int targetname) {
while (true) {
synchronized (lock) {
while (num % 3 != targetname) {
if(num>=10){//主线程没有退出
break;
}
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (num >=10) {
break;
}
num++;
System.out.print(Thread.currentThread().getName() + ":" + num);
lock.notifyAll();
}
}
}
}
结果:
A:1B:2C:3A:4B:5C:6A:7B:8C:9A:10
会发现结果和预想一样,那么同理线程数量增加时也是按照这个规律.
交替打印ABC问题
第一种
使用Lock对应的使用方法
public class thread4_1_100 {
private int num=0;
private Lock lock=new ReentrantLock();
private void printabc(String name,int targetnum){
for (int i = 0; i <10;) {
lock.lock();//加锁
if(num%3==targetnum){
num++;
i++;//确定是我要找的我才让i++
System.out.print(name);
}
lock.unlock();//操作完解锁
}
}
public static void main(String[] args) {
thread4_1_100 thread4_1_100=new thread4_1_100();
new Thread(()->{thread4_1_100.printabc("A",0);}).start();
new Thread(()->{thread4_1_100.printabc("B",1);}).start();
new Thread(()->{thread4_1_100.printabc("C",2);}).start();
}
}
结果:
ABCABCABCABCABCABCABCABCABCABC
第二种
使用join()方法 :
join() :与sleep() 方法一样,是一个可中断的方法,在一个线程中调用另一个线程的join() 方法,会使得当前的线程挂起,知直到执行join() 方法的线程结束。(!!)例如在B线程中调用A线程的join() 方法,B线程进入阻塞状态,直到A线程结束或者到达指定的时间。
既然是两个线程操作,是会有前后线程操作的
public class thread3_1_100 {
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i <10 ; i++) {
Thread t1 = new Thread(new printabc(null), "A");
Thread t2 = new Thread(new printabc(t1), "B");
Thread t3 = new Thread(new printabc(t2), "C");
t1.start();
t2.start();
t3.start();
Thread.sleep(10);//必须的
}
}
}
class printabc implements Runnable{
public printabc(Thread beforeThread) {
this.beforeThread = beforeThread;
}
private Thread beforeThread;
@Override
public void run() {
if(beforeThread!=null){//第一个线程是特例
try {
beforeThread.join();//前一个线程调用join()
System.out.print(Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
System.out.print(Thread.currentThread().getName()+"");
}
}
}
结果:
ABCABCABCABCABCABCABCABCABCABC
第三种
使用lock+Condition精准唤醒
需要唤醒哪个呢 就是A唤醒B,B唤醒C,C唤醒A依次循环
下一个线程.signal();方法
//精准唤醒
public class thread5_1_100 {
private int num;
private static Lock lock=new ReentrantLock();
private static Condition c1=lock.newCondition();
private static Condition c2=lock.newCondition();
private static Condition c3=lock.newCondition();
private void printabc(String name, int targetnum, Condition curthread,Condition nextthread){
for(int i=0;i<10;){
lock.lock();
while(num%3!=targetnum){
try {
curthread.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
num++;
i++;
System.out.print(name);
nextthread.signal();
lock.unlock();
}
}
public static void main(String[] args) {
thread5_1_100 thread5_1_100=new thread5_1_100();
new Thread(()->{thread5_1_100.printabc("A",0,c1,c2);}).start();
new Thread(()->{thread5_1_100.printabc("B",1,c2,c3);}).start();
new Thread(()->{thread5_1_100.printabc("C",2,c3,c1);}).start();
}
结果:
ABCABCABCABCABCABCABCABCABCABC
第四种
使用信号量
public class thread6_1_100 {
public Semaphore c1 = new Semaphore(1);
public Semaphore c2 = new Semaphore(0);
public Semaphore c3 = new Semaphore(0);
public static void main(String[] args) {
new thread6_1_100().printABC();
}
public void printABC() {
ExecutorService exe = Executors.newCachedThreadPool();
Thread t1 = new Thread() {
@Override
public void run() {
while (true) {
try {
c1.acquire();
System.out.print("A");
c2.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread t2 = new Thread() {
@Override
public void run() {
while (true) {
try {
c2.acquire();
System.out.print("B");
c3.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread t3 = new Thread() {
@Override
public void run() {
while (true) {
try {
c3.acquire();
System.out.print("C");
c1.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
exe.execute(t1);
exe.execute(t2);
exe.execute(t3);
}
}
来自大四学生(小白)的第二篇博客