Java实现多线程轮流打印1

网友投稿 346 2022-11-25


Java实现多线程轮流打印1

首先打印1-100数字如果用一个单线程实现那么只要一个for循环即可,那么如果要用两个线程打印出来呢?(一个线程打印奇数,一个线程打印偶数)于是大家会想到可以通过加锁实现,但是这样的效率是不是不高?这里我用一个变量来控制两个线程的输出

public class ThreadTest {

volatile int flag=0;

public void runThread() throws InterruptedException{

Thread t1=new Thread(new Thread1());

Thread t2=new Thread(new Thread2());

t1.start();

t2.start();

}

public class Thread1 implements Runnable{

public void run() {

int i=0;

while(i<=99){

if(flag==0)

{

System.out.println("t1="+i+"flag="+flag);

i+=2;

flag=1;

}

}

}

}

public class Thread2 implements Runnable{

public void run() {

int i=1;

while(i<=99){

if(flag==1)

{

System.out.println("t2="+i+"flag="+flag);

i+=2;

flag=0;

}

}

}

}

}

那么如果要实现三个线程轮流打印1-100的数字呢?是不是也可以用上面的方法实现呢?代码如下

public class ThreadTest {

private int i=0;

private Thread thread1,thread2,thread3;

private int flag=0;

public void runThread() throws InterruptedException{

thread1=new Thread(new Thread1());

thread2=new Thread(new Thread2());

thread3=new Thread(new Thread3());

thread1.start();

thread2.start();

thread3.start();

}

public class Thread1 implements Runnable{

public void run() {

while(i<=100){

if(flag==0) {

System.out.println("t1="+i);

i++;

flag=1;

}

}

}

}

public class Thread2 implements Runnable{

public void run() {

while(i<=100){

if(flag==1) {

System.out.println("t2="+i);

i++;

flag=2;

}

}

}

}

public class Thread3 implements Runnable{

public void run() {

while(i<=100){

if(flag==2) {

System.out.println("t3="+i);

i++;

flag=0;

}

}

}

}

}

运行结果

发现三个线程只打印了一次就停止不输出了,是什么原因呢?

可以用jdk自带的jstack来看看线程的状态,在windows系统中可以打开cmd然后进入jdk所在目录,然后执行Jsp,能查看到各线程id,然后执行jstack -F pid就可以看的状态了

可以看到几个Thread state是BLOCKED,就是阻塞了,什么原因呢?

尴尬发现flag变量和i变量前面忘记加volatile,导致flag和i被线程读取修改时,其他线程不可见,所以才导致上面的问题出现。

在JVM中每个线程读取变量到cache中时相互都是不可见的,也就是java五大内存区中的程序计数器区域对于每个线程都是独立的不共享的,只有堆内存区和方法区是对所有线程都是共享的。

当线程1读取了flag和i的值,并对其进行修改的时候,线程2并发运行,并不知道flag和i值已经改变,导致多线程数据不一致的情况,所以加了volatile后,当线程读取变量进行修改后会“通知”其它线程这个值已经进行了修改。

import java.util.concurrent.atomic.AtomicInteger;

public class ThreadTest {

private volatile int i=0;

private Thread thread1,thread2,thread3;

private volatile int flag=0;

public void runThread() throws InterruptedException{

thread1=new Thread(new Thread1());

thread2=new Thread(new Thread2());

thread3=new Thread(new Thread3());

thread1.start();

thread2.start();

thread3.start();

}

public class Thread1 implements Runnable{

public void run() {

while(i<100){

if(flag==0) {

System.out.println("t1="+i);

i++;

flag=1;

}

}

}

}

public class Thread2 implements Runnable{

public void run() {

while(i<100){

if(flag==1){

System.out.println("t2="+i);

i++;

flag=2;

}

}

}

}

public class Thread3 implements Runnable{

public void run() {

while(i<100){

if(flag==2){

System.out.println("t3="+i);

i++;

flag=0;

}

}

}

}

}

运行结果

-----未完-----

补充知识:Java n个线程轮流打印数字的问题

一、两个线程轮流打印数字。

加锁实现:

package lianxi;

/*

* 用锁实现两个线程轮流打印1——100

*/

public class Print1TO100TwoThread {

private Object lock = new Object();

private int i = 0;

Thread threadA = new Thread(new Runnable() {

@Override

public void run() {

while (i <= 100) {

synchronized (lock) {

try {

if (i > 100)

break;

System.out.println("threadA :" + (i++));

lock.notify();

lock.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

});

Thread threadB = new Thread(new Runnable() {

@Override

public void run() {

while (i <= 100) {

synchronized (lock) {

try {

if (i > 100)

brehttp://ak;

System.out.println("threadB :" + (i++));

lock.notify();

lock.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

});

public void startTwoThread() throws InterruptedException {

threadA.start();

Thread.sleep(20);

threadB.start();

}

public static void main(String[] args) throws InterruptedException {

new Print1TO100TwoThread().startTwoThread();

}

}

用锁效率太低,用一个变量来控制打印的顺序。

package lianxi;

/*

* 用两个线程轮流打印1——10;用所实现效率太低,用变量来控制

*/

public class PrinntNumTwoThread {

private volatile int num = 0;

private volatile boolean flag = false;

Thread threadA = new Thread(new Runnable() {

@Override

public void run() {

while (true) {

if (num > 10)

return;

if (!flag) {

System.out.println("threadA-->" + ":" + (num++));

flag = !flag;

}

}

}

});

Thread threadB = new Thread(new Runnable() {

@Override

public void run() {

while (true) {

if (num > 10)

return;

if (flag) {

System.out.println("threadB-->" + ":" + (num++));

flag = !flag;

}

}

}

});

public void startTwoThread() {

threadA.start();

threadB.start();

}

public static void main(String[] args) {

new PrinntNumTwoThread().startTwoThread();

}

}

二、那么如果要实现三个线程轮流打印1-100的数字呢?

package lianxi;

public class PrintNumThreeThread {

private volatile int i = 0;

private volatile int flag = 0;

Thread threadA = new Thread(new Runnable() {

@Override

public void run() {

while (true) {

if (i > 100)

return;

if (flag == 0) {

System.out.println("threadA->" + ":" + (i++));

flag = 1;

}

}

}

});

Thread threadB = new Thread(new Runnable() {

@Override

public void run() {

while (true) {

if (i > 100)

return;

if (flag == 1) {

System.out.println("threadB->" + ":" + (i++));

flag = 2;

}

}

}

});

ThroxdirJead threadC = new Thread(new Runnable() {

@Override

public void run() {

while (true) {

if (i > 100)

return;

if (flag == 2) {

System.out.println("threadC->" + ":" + (i++));

flag = 0;

}

}

}

});

public void startThreeThread() {

threadA.start();

threadB.start();

threadC.start();

}

public static void main(String[] args) {

new PrintNumThreeThread().startThreeThread();

}

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java多线程通信:交替打印ABAB实例
下一篇:利用Lambda表达式创建新线程案例
相关文章

 发表评论

暂时没有评论,来抢沙发吧~