日期:2014-05-20  浏览次数:20834 次

java多线程
我想实现一个两个线程对同一个变量,一个线程加,一个线程减的程序。可是打印的结果是1,2,3,4,5,6,7...而不是1,0,1,0..
想知道为什么
程序如下:
Java code
public class Core {
    public static void main(String[] args) throws Exception{
        Operation op = new Operation();
        WorkerBear b1 = new WorkerBear(op);
        EatBear b2 = new EatBear(op);
        Thread t1 = new Thread(b1);
        Thread t2 = new Thread(b2);
        t2.start();
        t1.start();
    }
}


Java code
public class WorkerBear implements Runnable{
    private Operation op;
    
    public WorkerBear(Operation op){
        this.op = op;
    }
    
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(true){
        op.increment();
        }
    }
}


Java code
public class EatBear implements Runnable{
    private Operation op;
    
    public EatBear(Operation op){
        this.op = op;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(true){ //如果这里加入一个Thread.sleep()就好使,为什么呢
        op.decrement();
        }
    }
}

Java code

public class Operation {
    int box = 0 ;
    
    public synchronized void increment() {
        box++;
        try {
            Thread.sleep(1000);
        System.out.println(box);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    public synchronized void decrement() {
        box--;
        try {
            Thread.sleep(1000);
        System.out.println(box);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}



------解决方案--------------------
汗,因为你把sleep(1000)放到同步方法里面了...
一个线程sleep的时候,没有释放锁,所以另一个线程无法执行
sleep完释放锁的时候,又没有做线程礼让,或唤醒其他线程的动作,系统把时间片仍然分给该线程,
所以就一直加加加
所以sleep(1000)要放在while循环中才行
------解决方案--------------------
探讨
那为什么我把sleep放在外面的时候B线程就能获得到锁呢,我也是没有唤醒B线程呀

------解决方案--------------------
探讨
是呀,那即使是thread1的increment()方法里面有一个sleep(),当increment()退出的时候,thread2的decrement()不同样是有可能获得cpu吗?为什么事实上只有thread1总是获得cpu呢?这点我不太懂

------解决方案--------------------
这里有个参考例子,希望对你有帮助:
Java code

/**
 * 
 */
package cn.luochengor.csdn;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 实现两个线程对同一个变量,一个线程加,一个线程减的程序 打印的结果是:1,0,1,0..
 * 
 * @Author luochengor
 * @Date Oct 25, 2011
 * @Email luochengor@foxmail.com
 */
public class OneZero {
    private int number = 0;
    private boolean isOne = false;

    public synchronized int toOne() {
        number++;
        isOne = true;
        notifyAll();
        return number;
    }

    public synchronized int toZero() {
        number--;
        isOne = false;
        notifyAll();
        return number;
    }

    public synchronized void waitToOne() throws InterruptedException {
        while (!isOne) {
            wait();
        }
    }

    public synchronized void waitToZero() throws InterruptedException {
        while (isOne) {
            wait();
        }
    }

    /**
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        OneZero oz = new OneZero();
        ExecutorService exec = Executors.newCachedThreadPool();
        exec.execute(new ToOne(oz));
        TimeUnit.MILLISECONDS.sleep(50);
        exec.execute(new ToZero(oz));
        TimeUnit.SECONDS.sleep(5);
        exec.shutdownNow();
    }

}

class ToOne implements Runnable {
    private OneZero oz;

    public ToOne(OneZero oz) {
        this.oz = oz;
    }

    public void run() {
        try {
            while (!Thread.interrupted()) {
                TimeUnit.MILLISECONDS.sleep(600);
                System.out.println(oz.toOne());
                oz.waitToZero();
            }
        } catch (InterruptedException e) {
            System.out.println("InterruptedException class ToOne");
        }
    }
}

class ToZero implements Runnable {
    private OneZero oz;

    public ToZero(OneZero oz) {
        this.oz = oz;
    }

    public void run() {
        try {
            while (!Thread.interrupted()) {
                TimeUnit.MILLISECONDS.sleep(600);
                System.out.println(oz.toZero());
                oz.waitToOne();
            }
        } catch (InterruptedException e) {
            System.out.println("InterruptedException class ToZero");
        }
    }
}