public class ThreadTestNum implements Runnable {
public static int num = 20; public static void main(String[] args) {
Thread t1=new Thread(new ThreadTestNum());
Thread t2=new Thread(new ThreadTestNum());
Thread t3=new Thread(new ThreadTestNum());
Thread t4=new Thread(new ThreadTestNum());
t1.start();
t2.start();
t3.start();
t4.start();
}
public void run(){
sale(Thread.currentThread().getName());
}
public void sale(String name){
while(num>0){
synchronized (this) {
System.out.println(name+" 运行到了num= "+num);
num--;
}
}
}
}
为什么在切换线程的时候会出现相等的错误?????谢谢大虾了!!!!!
public static int num = 20; public static void main(String[] args) {
Thread t1=new Thread(new ThreadTestNum());
Thread t2=new Thread(new ThreadTestNum());
Thread t3=new Thread(new ThreadTestNum());
Thread t4=new Thread(new ThreadTestNum());
t1.start();
t2.start();
t3.start();
t4.start();
}
public void run(){
sale(Thread.currentThread().getName());
}
public void sale(String name){
while(num>0){
synchronized (this) {
System.out.println(name+" 运行到了num= "+num);
num--;
}
}
}
}
为什么在切换线程的时候会出现相等的错误?????谢谢大虾了!!!!!
num--;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
试试
* file: Pause.java
* class: Pause
*
* description:
*
* @author: leisore
* @version: V1.0.0
*/
package cn.leisore.daily._2010_06_24;public class ClassLockDemo implements Runnable { public static int num = 20; public static void main(String[] args) { Thread t1 = new Thread(new ClassLockDemo());
Thread t2 = new Thread(new ClassLockDemo());
Thread t3 = new Thread(new ClassLockDemo());
Thread t4 = new Thread(new ClassLockDemo()); t1.start();
t2.start();
t3.start();
t4.start(); } public void run() {
sale(Thread.currentThread().getName());
} public void sale(String name) {
synchronized (ClassLockDemo.class) {
while (num > 0) {
System.out.println(name + " 运行到了num= " + num);
num--;
try {
ClassLockDemo.class.wait(100);
ClassLockDemo.class.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public void sale(String name){
synchronized (ThreadTestNum.class) {
while(num>0){
System.out.println(name+" 运行到了num= "+num);
num--;
}
}
}
public void sale(String name){
while(num>0){
synchronized (ThreadTestNum.class) {
try{
Thread.sleep(1);
}catch(Exception e){}
if(num>0){
System.out.println(name+" 运行到了num= "+num);
num--;
}
}
}
//这样更符合逻辑!多跑几次才明显
将num放入同步代码块中,更加安全
package a;public class ThreadTestNum implements Runnable {public static int num = 20;public static void main(String[] args) {Thread t1=new Thread(new ThreadTestNum());
Thread t2=new Thread(new ThreadTestNum());
Thread t3=new Thread(new ThreadTestNum());
Thread t4=new Thread(new ThreadTestNum());t1.start();
t2.start();
t3.start();
t4.start();}
public void method(){
this.num--;
}public void run(){
sale(Thread.currentThread().getName());
}public void sale(String name){
while(num>0){
synchronized (this) {
this.method();
System.out.println(name+" 运行到了num= "+num);
}
}
}
}
Thread-1 运行到了num= 18
Thread-2 运行到了num= 17
Thread-3 运行到了num= 16
Thread-1 运行到了num= 15
Thread-2 运行到了num= 14
Thread-3 运行到了num= 13
Thread-1 运行到了num= 12
Thread-2 运行到了num= 11
Thread-3 运行到了num= 10
Thread-0 运行到了num= 9
Thread-2 运行到了num= 8
Thread-3 运行到了num= 7
Thread-0 运行到了num= 5
Thread-1 运行到了num= 5
Thread-2 运行到了num= 4
Thread-3 运行到了num= 3
Thread-0 运行到了num= 2
Thread-1 运行到了num= 1
Thread-2 运行到了num= 0
说一下楼主错误的原因:sychonize(this)意思是指锁住当前的引用的对象没错,但是你实例化了另外四个Thread对象,对他们你是没有上锁的,所以他们如果都start()以后,是并行运行的,num的值在输出时就会出现问题,所以要想num的值稳定向下减少,这几个进程就要排队获得对(this)当前引用对象的操作,这样你对(this)加上synchronized才会有效果,就是说这几个启动对像每一次只能有一个进程获得(this)对象,其它都得等待,所以才会出现正确结果。呵呵,过去我也经常出现这种错误,不知楼主明白了没?
当然会报错。
在我机器上的结果:Thread-0 运行到了num= 18
Thread-0 运行到了num= 17
Thread-0 运行到了num= 16
Thread-0 运行到了num= 15
Thread-0 运行到了num= 14
Thread-0 运行到了num= 13
Thread-0 运行到了num= 12
Thread-0 运行到了num= 11
Thread-0 运行到了num= 10
Thread-1 运行到了num= 18
Thread-1 运行到了num= 8
Thread-1 运行到了num= 7
Thread-0 运行到了num= 9
Thread-1 运行到了num= 6
Thread-1 运行到了num= 4
Thread-0 运行到了num= 5
Thread-3 运行到了num= 1
Thread-1 运行到了num= 2
Thread-2 运行到了num= 3
Thread-0 运行到了num= 018出现了两次
说明不是现线程安全的哦
Thread t2=new Thread(new ThreadTestNum());
Thread t3=new Thread(new ThreadTestNum());
Thread t4=new Thread(new ThreadTestNum());
总共4个ThreadTestNum对象实例,synchronized (this)是在四个完全独立的对象上加锁,彼此没有任何关系,根本无法同步!不知道就别瞎说。
java多线程要求synchronized包起来的必须是Runnable的对象,明白了吧。你的this是什么?是Thread的一个子类,自然就是Runnable的子类。
在这里是可以同步的,因为有一个static的类变量
while(num>0){
synchronized (this) {
this.method();//其实就是this.num--;
System.out.println(name+" 运行到了num= "+num);
}
}
假如现num=1,线程1执行到while(num>0),判断结果是true,切换到线程2,此时线程2判断肯定也是true。然后,锁住线程2的ThreadTestNum这个对象,this.num--;num变为0,这时候切换到线程1,同样可以进入this.method();因为这是获得另外一个ThreadTestNum对象的锁,同样this.num--;num就变为-1了。运行暂时没错,不代表永远没错。多跑几次就知道了
18楼是对的public class ThreadTestNum implements Runnable {
public static int num = 20; public static void main(String[] args) {
ThreadTestNum test = new ThreadTestNum();
Thread t1=new Thread(test);
Thread t2=new Thread(test);
Thread t3=new Thread(test);
Thread t4=new Thread(test); t1.start();
t2.start();
t3.start();
t4.start(); }
public void run(){
sale(Thread.currentThread().getName());
} public void sale(String name){
synchronized (this){
while(this.num>0){
this.num--;
System.out.println(name+" it's num= "+num);
try {
this.notifyAll();
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
你这里如果要实现多个线程共享工作,就要wait notify,否则对象就一直被同一个下称锁着
int num = 200; public void count_num() {
this.num--;
} public static void main(String args[]) {
Count c = new Count();
ThreadNum t1 = new ThreadNum(c);
ThreadNum t2 = new ThreadNum(c);
ThreadNum t3 = new ThreadNum(c);
ThreadNum t4 = new ThreadNum(c);
t1.start();
t2.start();
t3.start();
t4.start();
}
}class ThreadNum extends Thread {
Count t_;
String name; public ThreadNum(Count t) {
this.t_ = t;
} public void run() {
while (true) {
synchronized (t_) {
this.name = Thread.currentThread().getName();
/*try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
if(t_.num > 0){
t_.count_num();
}else{
break;
}
System.out.println(this.name + " " + t_.num);
}
}
}
}
不用wait()和notify()是可以的,你说的没错,至少我觉得,我上面说的也太绝对
直接用线程安全的 AtomicInteger 就行了
public static AtomicInteger num = new AtomicInteger(20);//线程安全的整数
public static Random rd = new Random();//随机数public void sale(String name) {
int n;
while ((n = num.decrementAndGet()) >= 0) {//将整数减一并返回当前值
System.out.println(name + " 运行到了num= " + n);
try {
Thread.sleep(rd.nextInt(20)+1);//随机休眠 1-20毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Thread t2=new Thread(new ThreadTestNum());
Thread t3=new Thread(new ThreadTestNum());
Thread t4=new Thread(new ThreadTestNum());问题很大,你应该只要一个ThreadTestNum tt = new ThreadTestNum()实例,,t1,t2,t3,t4中改成tt,