问一个关于线程的问题,一直不是弄的很清楚!
package com.pos.test;
public class SimpleThread extends Thread {
public int countDown = 5;
private static int threadCount = 0;
private int threadNumber = ++threadCount;
public SimpleThread(){
System.out.println( "making "+threadNumber);
}
public void run(){
while(true){
System.out.println( "thread "+threadNumber+ "( "+countDown+ ") ");
if(--countDown==0) return;
}
}
/**
* @param args
*/
public static void main(String[] args) {
for(int i =0;i <5;i++)
new SimpleThread().start();
System.out.println( "end ");
}
}
这是thinkinjava的原程序,运行是正常的,下面是我改的程序,问什么就发生了并发的问题,刚开始学习线程,对同一个类实例化的线程对象是否共享一块内存,是否每个对象中的变量相互独立弄的不是很清楚,希望有知道的能给我一点帮助!
public class SimpleThread implements Runnable {
public int countDown = 5;
private static int threadCount = 0;
private int threadNumber = ++threadCount;
public SimpleThread(){
System.out.println( "making "+threadNumber);
}
public void run(){
while(true){
System.out.println( "thread "+threadNumber+ "( "+countDown+ ") ");
if(--countDown==0) return;
}
}
/**
* @param args
*/
public static void main(String[] args) {
SimpleThread st = new SimpleThread();
for(int i =0;i <5;i++)
new Thread(st).start();
System.out.println( "end ");
}
}
[解决办法]
把你第二个程序改了一下:
package com.whj.jdk.lang;
public class SimpleThread extends Thread {
private static int threadCount = 0;
/**
* @param args
*/
public static void main(String[] args) {
SimpleThread st = new SimpleThread(); // Error Code
for (int i = 0; i < 5; i++) {
// new SimpleThread().start();
new Thread(st).start(); // Error Code
}
System.out.println( "end ");
}
public int countDown = 5;
private final int threadNumber = ++threadCount;
public SimpleThread() {
System.out.println( "making " + threadNumber);
}
@Override
public void run() {
while (true) {
System.out.println( "thread " + threadNumber + "( " + countDown + ") ");
if (--countDown == 0) {
System.out.println( "GO ");
return;
}
}
}
}
运行后的输出结果是:
making 1
end
thread1(5)
thread1(4)
thread1(3)
thread1(2)
thread1(1)
GO
thread1(0)
thread1(-1)
thread1(-2)
thread1(-3)
thread1(-4)
thread1(-5)
thread1(-6)
thread1(-7)
thread1(-8)
thread1(-9)
thread1(-10)
thread1(-11)
thread1(-12)
thread1(-13)
thread1(-14)
以下被我中断。
你仔细分析一下就知道为什么了。
[解决办法]
您的第一个程序的运行结果是:
making 1
making 2
making 3
making 4
making 5
end
thread2(5)
thread4(5)
thread1(5)
thread4(4)
thread2(4)
thread1(4)
thread4(3)
thread2(3)
thread1(3)
thread3(5)
thread4(2)
thread5(5)
thread2(2)
thread1(2)
thread3(4)
thread4(1)
thread5(4)
thread2(1)
thread1(1)
thread3(3)
thread5(3)
thread3(2)
thread5(2)
thread3(1)
thread5(1)
从这结果我们可以看出来,这个测试程序创建了5个线程,并且这5个线程是相互独立的,即它们对各自countDown 变量进行操作(每次减1,一共执行5次),所以5个线程一共执行25次,对应上面的结果的25行。他们并不是对countDown 进行并发访问,此时countDown 不是共享的资源
而你的第二个程序明显有错误,既然SimpleThread 是实现了Runnable接口,并且在测试的代码中用同一SimpleThread 的对象创建了5个线程,所以这5个线程共享了资源countDown ,即它们对countDown 一同进行操作,所以一定要提供对变量countDown 的并发操作。
这是我修改了你的代码
package threadTest;
public class SimpleThread implements Runnable {
private int countDown = 25;
//private static int threadCount = 0;
//private int threadNumber = ++threadCount;
String str= new String( " ");
public void run(){
while(true){
synchronized(str){
if(countDown > 0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " :( " + countDown-- + ") " );
//System.out.println( "thread " + threadNumber + "( " + --countDown + ") ");
}
}
}
}
/**
* @param args
*/
public static void main(String[] args) {
SimpleThread st = new SimpleThread();
for(int i =0;i <5;i++)
new Thread(st).start();
}
}
在上面我注释了你有毛病的地方。你只创建了一个SimpleThread实例,且threadCount是静态的变量,所以threadNumber一直是1,输出的结果永远是thread1,尽管你创建了5个线程。
这是我的测试结果,我把countDown 设为25,以便更好的观察结果
Thread-1 :(25)
Thread-0 :(24)
Thread-2 :(23)
Thread-3 :(22)
Thread-4 :(21)
Thread-1 :(20)
Thread-0 :(19)
Thread-2 :(18)
Thread-3 :(17)
Thread-4 :(16)
Thread-1 :(15)
Thread-0 :(14)
Thread-2 :(13)
Thread-3 :(12)
Thread-4 :(11)
Thread-1 :(10)
Thread-0 :(9)
Thread-2 :(8)
Thread-3 :(7)
Thread-4 :(6)
Thread-1 :(5)
Thread-0 :(4)
Thread-2 :(3)
Thread-3 :(2)
Thread-4 :(1)
从上面可以看出5个线程对变量countDown 进行了并发访问,5个线程一共进行了25次操作