关于java多线程的一个问题(为什么下面这个代码不是按照0~99顺序输出的?明明加锁了啊。。)

public class Test {

/**
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub
    for(int i=0;i<10;i++){
        MyThread myThread=new MyThread();
        myThread.start();
        try {
            myThread.sleep(1);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

}
class MyThread extends Thread{

@Override
public synchronized void  run() 
{
    // TODO Auto-generated method stub
    for(int i=0;i<100;i++)
    {
        System.out.println(i);
    }
}

}


你这样的写法根本就不涉及线程安全的问题,这十个线程都是运行各自的方法,根本就没有互斥的资源。你应该创建一个类,用十个线程分别调用那个类的同一个对象的同一个方法,这样你就会得到你想要的效果了。

编译了一下,代码是按照0~9输出的

编译了一下,代码是按照0~99输出的

我在线运行了下,是按照顺序输出的
http://ideone.com/bP5RCh

public class Test {

/**
 * @param args
 */
public static void main(String[] args) {
      // TODO Auto-generated method stub
    for(int i=0;i<10;i++){
        MyThread myThread=new MyThread();

        try {
            myThread.sleep(100);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        myThread.start();
    }

}

}
class MyThread extends Thread{
@Override
public synchronized void run()
{
// TODO Auto-generated method stub
for(int i=0;i<100;i++)
{
System.out.println(i);
}
}
}

在方法上加synchronized相当于synchronized(this),每个new出的MyThread对象,都得到了各自的锁,所以多个线程同时在运行

线程是不安全的,很有可能在I还没有自增之前,另一个线程也运行到了同样的地方,导致会输出2次1或者其他的,如果要输出其他的需要加锁也就是synchronized

public class MyThread implements Runnable {
private TestClass tc;
public MyThread(TestClass tc) {
super();
this.tc = tc;
}

@Override
public void run() {
    tc.add();
}

}

public class TestClass {
private int i;
public synchronized void add(){
for(i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}

public class TestMain {
public static void main(String[] args) throws Exception {
TestClass tc =new TestClass();
for(int i=0;i<10;i++){
new Thread(new MyThread(tc)).start();
}
}
}

不知道这是不是你想要的效果

public class TestClass {
private int i=0;
public synchronized void add(){
if(i<100){
System.out.println(Thread.currentThread().getName()+":"+(i++));
}
}
public int getI() {
return i;
}

}

public class MyThread implements Runnable {
private TestClass tc;
public MyThread(TestClass tc) {
super();
this.tc = tc;
}

@Override
public void run() {
    while(tc.getI()<100){
        tc.add();
    }
}

}

public class TestMain {
public static void main(String[] args) throws Exception {
TestClass tc =new TestClass();
for(int i=0;i<10;i++){
new Thread(new MyThread(tc)).start();
}
}
}

不好意思,前面的代码有点问题,稍微修改了一下

1.提主的代码确实是按照顺序输出的
2.提主其实想问的问题应该是:
关于java多线程的一个问题(为什么下面这个代码不是按照0~99顺序输出的?明明加锁了啊。。)

public class Test {
    public static void main(String[] args) {
        for(int i=0;i<10;i++){
            MyThread myThread=new MyThread();
            myThread.start();
        }
    }
}
class MyThread extends Thread {
    public synchronized void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(i);
            try {
                sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

3.为什么上面的代码不是顺序输出呢?
因为public synchronized void run()这里的synchronized使用的锁对象是是“当前对象”,而“当前对象”是在循环中创建的,
“当前对象”每循环一次都是不一样的,也就是说每次public synchronized void run()使用的锁是不一样的,既然锁是不一样的,那当然就没有什么用了。

 for(int i=0;i<10;i++){
            MyThread myThread=new MyThread();
            myThread.start();
        }

4.如何使程序顺序输出呢?

class MyThread extends Thread {
    public void run() {
        synchronized (MyThread.class) {
            for (int i = 0; i < 100; i++) {
                System.out.println(i);
                try {
                    sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}