Java基础篇之并发控制(二)

有了并发就可以同时干多件事情了,但是,两个或多个线程彼此相互干涉的问题也就出现了。如果不防范这种冲突,就可能导致两个线程试图同时访问同一个银行账户,或向同一台打印机打印,改变同一个值等诸如此类的东西。
考虑下面的一个列子,其中一个任务产生偶数,当数字是偶数时程序会永远的运行下去,但是当程序的数字是奇数时,程序会打印输出并且返回值。

package Day02;

public abstract class IntGenerator {
    private volatile boolean canceled = false;
    public abstract int next();
    public void cancel(){canceled = true;}
    public boolean isCanceled(){return canceled;}
}
package Day02;

public class EvenGenerator extends IntGenerator {

    private int currentEvenValue = 0;

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        EvenChecker.test(new EvenGenerator());
    }

    @Override
    public int next() {
        // TODO Auto-generated method stub
        ++currentEvenValue;
        ++currentEvenValue;
        ++currentEvenValue;
        ++currentEvenValue;
        return currentEvenValue;
    }

}
package Day02;

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

public class EvenChecker implements Runnable{

    public static void main(String[] args) {
        // TODO Auto-generated method stub

    }
    private IntGenerator generator;
    private final int id;


    public EvenChecker(IntGenerator generator, int id) {
        super();
        this.generator = generator;
        this.id = id;
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(!generator.isCanceled()){
            int value = generator.next();
            if( value % 2 !=0){
                System.out.println(value + " not even!");
                generator.cancel();
            }
        }
    }

    public static void test(IntGenerator gp,  int count){
        ExecutorService exec = Executors.newCachedThreadPool();
        for(int i=0;i<count;i++){
            exec.execute(new EvenChecker(gp, i));
        }
        exec.shutdown();
    }
    public static void test(IntGenerator gp){

        test(gp,10);
    }



}

上述代码中一共启动了10个线程,很显然10个线程去挣一个资源就会出现问题(运行代码就会很快退出),但是如果仅启动一个线程就不会出现问题,程序会一直运行下去。这就是线程安全问题,共享资源问题,为了解决这个问题,可以使用synchronized关键字:

package Day02;

public class SynchronizedEvenGenerator extends IntGenerator {

    private int currentEvenValue = 0;

    public static void main(String[] args) {
        // TODO Auto-generated method stub

    }

    @Override
    public synchronized int next() {
        // TODO Auto-generated method stub
        ++currentEvenValue;
        Thread.yield();//释放资源,公平竞争
        ++currentEvenValue;
        Thread.yield();
        ++currentEvenValue;
        Thread.yield();
        ++currentEvenValue;
        Thread.yield();
        return currentEvenValue;
    }

}

你可能感兴趣的:(java,并发,线程)