18
回答
这个多线程哪里出错了..
华为云实践训练营,热门技术免费实践!>>>   

 线程类

public class MyThread implements Runnable {
	
	static Integer i = new Integer(0);
	
	@Override
	public void run() {
		while(true) {
			synchronized (i) {
				if(i<100) {
					i++;
					String currentThreadName = Thread.currentThread().getName(); 
					System.out.println(currentThreadName+" i = "+i);
				}
			}
		}
		
	}

}

main

public class Test {
	public static void main(String[] args) {
		Thread t1 = new Thread(new MyThread());
		Thread t2 = new Thread(new MyThread());
		t1.start();
		t2.start();
		
	}
}

执行结果

Thread-0 i = 2
Thread-1 i = 2
Thread-1 i = 3
Thread-1 i = 4
Thread-1 i = 5
Thread-1 i = 6
Thread-1 i = 7
Thread-1 i = 8
Thread-1 i = 9
Thread-1 i = 10
Thread-1 i = 11
Thread-1 i = 12
Thread-1 i = 13
Thread-1 i = 14
Thread-1 i = 15
Thread-1 i = 16
Thread-1 i = 17
Thread-1 i = 18
Thread-1 i = 19
Thread-1 i = 20
Thread-1 i = 21
Thread-1 i = 22
Thread-1 i = 23
Thread-1 i = 24
Thread-1 i = 25
Thread-1 i = 26
Thread-1 i = 27
Thread-1 i = 28
Thread-1 i = 29
Thread-1 i = 30
Thread-1 i = 31
Thread-1 i = 32
Thread-1 i = 33
Thread-1 i = 34
Thread-1 i = 35
Thread-1 i = 36
Thread-1 i = 37
Thread-1 i = 38
Thread-1 i = 39
Thread-1 i = 40
Thread-1 i = 41
Thread-1 i = 42
Thread-1 i = 43
Thread-1 i = 44
Thread-1 i = 45
Thread-1 i = 46
Thread-1 i = 47
Thread-1 i = 48
Thread-1 i = 49
Thread-1 i = 50
Thread-1 i = 51
Thread-1 i = 52
Thread-1 i = 53
Thread-1 i = 54
Thread-1 i = 55
Thread-1 i = 56
Thread-1 i = 57
Thread-1 i = 58
Thread-1 i = 59
Thread-1 i = 60
Thread-1 i = 61
Thread-1 i = 62
Thread-1 i = 63
Thread-1 i = 64
Thread-1 i = 65
Thread-1 i = 66
Thread-1 i = 67
Thread-1 i = 68
Thread-1 i = 69
Thread-1 i = 70
Thread-1 i = 71
Thread-1 i = 72
Thread-1 i = 73
Thread-1 i = 74
Thread-1 i = 75
Thread-1 i = 76
Thread-1 i = 77
Thread-1 i = 79
Thread-1 i = 80
Thread-1 i = 81
Thread-1 i = 82
Thread-1 i = 83
Thread-1 i = 84
Thread-1 i = 85
Thread-1 i = 86
Thread-1 i = 87
Thread-1 i = 88
Thread-1 i = 89	
Thread-1 i = 90
Thread-1 i = 91
Thread-1 i = 92
Thread-1 i = 93
Thread-1 i = 94
Thread-1 i = 95
Thread-1 i = 96
Thread-1 i = 97
Thread-1 i = 98
Thread-1 i = 99
Thread-1 i = 100
Thread-0 i = 78

我想要的是

Thread-0 i = 1
Thread-1 i = 2
Thread-0 i = 3
Thread-1 i = 4
Thread-0 i = 5
Thread-1 i = 6
。。。。

web出身不懂线程,请赐教..

举报
共有18个答案 最后回答: 7天前

你的两个线程的static Integer i = new Integer(0);  这个是线程里面私有的,每个线程都是单独一份

你应该放在public class Test  这个类里面,然后线程里面改成

synchronized (test.i)

--- 共有 4 条评论 ---
不日小鸡 回复 @月亮上好冷 : 你看评论啊,我不是说我看错了么 1周前 回复
月亮上好冷synchronized (test.i) 还是不行哦!! 1周前 回复
不日小鸡 回复 @xiaobaibae : 哎哟,看错了,你说得对 1周前 回复
xiaobaibae兄弟,static变量是所有对象共享的吧 1周前 回复

实际上并没有错,只是打印是需要时间的,线程1和线程2同时执行了对i++的操作,

 线程1把i变成了1

线程2把i变成了2

然后线程1才慢吞吞的进行打印,所以这个时候打出来了2

实际上i本身的++操作是没问题的

你这个问题出在了你的锁块被拆开了相当于多个实例的锁块每个实例锁块只执行一次,没什么意义,单独把任务提取出来单独加锁就 

 

两个线程交替执行,一个输出偶数,一个输出奇数

  1. 正整型数的轮番打印,需要一个共同的资源 Num
  2. 必须用这个资源作为参数来创建两个线程:一个负责输出偶数,一个负责输出奇数。即,这两个线程共享这个资源。
  3. 为了保证这两个线程交替执行打印任务,必须在这个资源内加一个标志/信号旗(布尔变量 flag)。
  4. 用这个标志/信号旗, 再加上合理使用Object 类(任何用java定义的类,都继承了 Object)的 wait() 和 notify() 方法,才能达到 这两个线程交替工作 的目的。
  5. 修改过的代码如下。输出结果将如你所愿。

 

public class MyThreadTest {
	static Num num;

//由两线程共享的 打印资源,数字从 0 开始
static class Num {
    int i=0;
    boolean flag = false; //两个线程,交替执行的一个标志
}

//打印偶数的线程
static class PrintEven implements Runnable{
    Num num ;
    public PrintEven(Num num)
    {
        this.num = num;
    }
    public void run()
    {
        while(num.i<= 100) //打印到100跳出循环体
        {   
            synchronized (num) { /* 必须要用一把锁对象,这个对象是num*/
                if(num.flag) //若标志为true
                {
                    try {
                        num.wait(); //操作wait()函数,表示被锁住,等待执行打印
                    } catch (Exception e) {
                    }
                }
                else {
/* 初始标志为 false,初始值为 0,
 * 负责打印偶数的线程帅先打印 0  */
                    System.out.println("偶数-----"+num.i);
                    num.i++; //打印资源变量1自增1
                    num.flag = true;//打印完成,资源变量1也更新完毕,故改变标志
                    num.notify();//通知奇数线程:不必等待,可以打印了
                }
            }
        }
    }
}

//打印奇数的线程
static class PrintOdd implements Runnable{
    Num num;
    public PrintOdd(Num num) {
        this.num = num;
    }
    public void run()
    {
        while(num.i<=100)
        {
            synchronized (num)/* 必须要用一把锁对象,这个对象是num*/ {
                if(!num.flag)//若标志为false
                {
                    try 
                    {
                        num.wait();  //操作wait()函数,表示被锁住,等待执行打印
                    } catch (Exception e) 
                    {}
                }   
                else {

/* 标志 flag 变为 true,数值变为 1,
 * 负责打印奇数的线程开始打印,
 * 打印的第一个值是 1  */                    
					System.out.println("奇数-----"+num.i);
                    num.i++; //打印资源变量1自增1
                    num.flag = false;//打印完成,资源变量1也更新完毕,故改变标志
                    num.notify();//通知偶数线程:不必等待,可以打印了
                }
            }
        }
    }
}


//主方法
    public static void main(String[] args) {
        num = new Num(); //创建一个打印资源
        
/* 用创建的资源 num,作参数,分别创建打印奇数和偶数的 Runnable 对象。
 * 这样一来,两个对象就共享这个资源num 
 */
        PrintEven pEven = new PrintEven(num);
        PrintOdd  pOdd  = new PrintOdd(num);

        Thread aThread = new Thread(pEven); //生成打印偶数的线程 aThread
        Thread bThread = new Thread(pOdd);  //生成打印奇数的线程 bThread

        aThread.start(); //启动打印偶数的线程 aThread
        bThread.start(); //启动打印奇数的线程 bThread
    }
}

输出:

D:\java\test\Thread>javac MyThreadTest.java

D:\java\test\Thread>java MyThreadTest
偶数-----0
奇数-----1
偶数-----2
奇数-----3
偶数-----4
奇数-----5
偶数-----6
奇数-----7
偶数-----8
奇数-----9
偶数-----10
奇数-----11
偶数-----12
奇数-----13
偶数-----14
奇数-----15
偶数-----16
奇数-----17
偶数-----18
奇数-----19
偶数-----20
奇数-----21
偶数-----22
奇数-----23
偶数-----24
奇数-----25
偶数-----26
奇数-----27
偶数-----28
奇数-----29
偶数-----30
奇数-----31
偶数-----32
奇数-----33
偶数-----34
奇数-----35
偶数-----36
奇数-----37
偶数-----38
奇数-----39
偶数-----40
奇数-----41
偶数-----42
奇数-----43
偶数-----44
奇数-----45
偶数-----46
奇数-----47
偶数-----48
奇数-----49
偶数-----50
奇数-----51
偶数-----52
奇数-----53
偶数-----54
奇数-----55
偶数-----56
奇数-----57
偶数-----58
奇数-----59
偶数-----60
奇数-----61
偶数-----62
奇数-----63
偶数-----64
奇数-----65
偶数-----66
奇数-----67
偶数-----68
奇数-----69
偶数-----70
奇数-----71
偶数-----72
奇数-----73
偶数-----74
奇数-----75
偶数-----76
奇数-----77
偶数-----78
奇数-----79
偶数-----80
奇数-----81
偶数-----82
奇数-----83
偶数-----84
奇数-----85
偶数-----86
奇数-----87
偶数-----88
奇数-----89
偶数-----90
奇数-----91
偶数-----92
奇数-----93
偶数-----94
奇数-----95
偶数-----96
奇数-----97
偶数-----98
奇数-----99
偶数-----100

D:\java\test\Thread>

 

--- 共有 7 条评论 ---
tcxu 回复 @在下路哥 : 同时要求登陆的用户,可能千千万,但服务器的能力有限。 由网上 查到:https://zhidao.baidu.com/question/1733448891338477227.html 7天前 回复
tcxu 回复 @在下路哥 : MySQL服务器的最大并发连接数是16384。 受服务器配置,及网络环境等制约,实际服务器支持的并发连接数会小一些。主要决定因素有: 1、服务器CPU及内存的配置。 2、网络的带宽。互联网连接中上行带宽的影响尤为明显。 7天前 回复
开源中国-林俊杰mysql并发是多少? 7天前 回复
tcxu 回复 @BoXuan : 你可能没彻底搞懂楼主的最终诉求。他希望的,就是两个线程要交替执行:两个线程,一个负责打印奇数,另一个负责打印偶数,同步执行任务,数字则按顺序输出。 1周前 回复
BoXuan 回复 @tcxu : 哦,这样啊,我是按楼主的最终需求讨论的,你这边要交替执行,抱歉 1周前 回复

你的锁Integer i 应该是两个线程共有的,你这样是给每个线程了一个锁,他们之间没关系,就算你给了同一个锁对象,你问题里的写法也不能保证是交替执行,你得要用到wait(), notify(),

--- 共有 1 条评论 ---
tcxu建议中肯。我已经按你的建议,修改了楼主的代码,输出了满意的结果。 1周前 回复
顶部