课程咨询 :186 8716 1620      qq:2066486918

昆明Java培训 > 达内新闻 > Java多线程发展简史
  • Java多线程发展简史

    发布:昆明Java培训      来源:达内新闻      时间:2016-03-09


  • 昆明java培训机构首先问这样一个问题,如果提到Java多线程编程,你会想到什么?

    volatilesynchronized关键字?

    竞争和同步?

    锁机制?

    线程安全问题?

    线程池和队列?

    好吧,请原谅昆明java培训机构在这里卖的关子,其实这些都对,但是又不足够全面,如果我们这样来谈论Java多线程会不会全面一些:

    可是,这未免太死板了,不是么?

    不如换一个思路,我们少谈一些很容易查到的语法,不妨从历史的角度看看Java在多线程编程方面是怎样进化的,这个过程中,它做了哪些正确的决定,犯了哪些错误,未来又会有怎样的发展趋势?

    另外,还有一点要说是,我希望通过大量的实例代码来说明这些事情。Linus说:“Talk is cheap, show me the code.”

    诞生

    Java的基因来自于199012Sun公司的一个内部项目,目标设备正是家用电器,但是C++的可移植性和API的易用性都让程序员反感。旨在解决这样的问题,于是又了Java的前身Oak语言,但是知道19953月,它正式更名为Java,才算Java语言真正的诞生。

    JDK 1.0

    19961月的JDK1.0版本,从一开始就确立了Java最基础的线程模型,并且,这样的线程模型再后续的修修补补中,并未发生实质性的变更,可以说是一个具有传承性的良好设计。

    抢占式和协作式是两种常见的进程/线程调度方式,操作系统非常适合使用抢占式方式来调度它的进程,它给不同的进程分配时间片,对于长期无响应的进程,它有能力剥夺它的资源,甚至将其强行停止(如果采用协作式的方式,需要进程自觉、主动地释放资源,也许就不知道需要等到什么时候了)。Java语言一开始就采用协作式的方式,并且在后面发展的过程中,逐步废弃掉了粗暴的stop/resume/suspend这样的方法,它们是违背协作式的不良设计,转而采用wait/notify/sleep这样的两边线程配合行动的方式。

    一种线程间的通信方式是使用中断:

    public class InterruptCheck extends Thread {

    @Override

    public void run() {

    System.out.println("start");

    while (true)

    if (Thread.currentThread().isInterrupted())

    break;

    System.out.println("while exit");

    }

    public static void main(String[] args) {

    Thread thread = new InterruptCheck();

    thread.start();

    try {

    sleep(2000);

    } catch (InterruptedException e) {

    }

    thread.interrupt();

    }

    }

    这是中断的一种使用方式,看起来就像是一个标志位,线程A设置这个标志位,线程B时不时地检查这个标志位。另外还有一种使用中断通信的方式,如下:

    public class InterruptWait extends Thread {

    public static Object lock = new Object();

    @Override

    public void run() {

    System.out.println("start");

    synchronized (lock) {

    try {

    lock.wait();

    } catch (InterruptedException e) {

    System.out.println(Thread.currentThread().isInterrupted());

    Thread.currentThread().interrupt(); // set interrupt flag again

    System.out.println(Thread.currentThread().isInterrupted());

    e.printStackTrace();

    }

    }

    }

     

    public static void main(String[] args) {

    Thread thread = new InterruptWait();

    thread.start();

    try {

    sleep(2000);

    } catch (InterruptedException e) {

    }

    thread.interrupt();

    }

    }

    在这种方式下,如果使用wait方法处于等待中的线程,被另一个线程使用中断唤醒,于是抛出InterruptedException,同时,中断标志清除,这时候我们通常会在捕获该异常的地方重新设置中断,以便后续的逻辑通过检查中断状态来了解该线程是如何结束的。

    在比较稳定的JDK 1.0.2版本中,已经可以找到ThreadThreadUsage这样的类,这也是线程模型中最核心的两个类。整个版本只包含了这样几个包:java.io java.utiljava.netjava.awtjava.applet,所以说Java从一开始这个非常原始的版本就确立了一个持久的线程模型。

    值得一提的是,在这个版本中,原子对象AtomicityXXX已经设计好了,这里给出一个例子,说明i++这种操作时非原子的,而使用原子对象可以保证++操作的原子性:

    import java.util.concurrent.atomic.AtomicInteger;

    public class Atomicity {

    private static volatile int onAtomicCounter = 0;

    private static volatile AtomicInteger atomicCounter = new AtomicInteger(0);

    private static int times = 0;

    public static void caculate() {

    times++;

    for (int i = 0; i < 1000; i++) {

    new Thread(new Runnable() {

    @Override

    public void run() {

    nonAtomicCounter++;

    atomicCounter.incrementAndGet();

    }

    }).start();

    }

    try {

    Thread.sleep(1000);

    } catch (InterruptedException e) {

    }

    }

    public static void main(String[] args) {

    caculate();

    while (nonAtomicCounter == 1000) {

    nonAtomicCounter = 0;

    atomicCounter.set(0);

    caculate();

    }

    System.out.println("Non-atomic counter: " + times + ":"

    + nonAtomicCounter);

    System.out.println("Atomic counter: " + times + ":" + atomicCounter);

    }

    }

    昆明java培训上面这个例子你也许需要跑几次才能看到效果,使用非原子性的++操作,结果经常小于1000

    对于锁的使用,网上可以找到各种说明,但表述都不够清晰。请看下面的代码:

    public class Lock {

    private static Object o = new Object();

    static Lock lock = new Lock();

     

    // lock on dynamic method

    public synchronized void dynamicMethod() {

    System.out.println("dynamic method");

    sleepSilently(2000);

    }

     

    // lock on static method

    public static synchronized void staticMethod() {

    System.out.println("static method");

    sleepSilently(2000);

    }

     

    // lock on this

    public void thisBlock() {

    synchronized (this) {

    System.out.println("this block");

    sleepSilently(2000);

    }

    }

     

    // lock on an object

    public void objectBlock() {

    synchronized (o) {

    System.out.println("dynamic block");

    sleepSilently(2000);

    }

    }

     

    // lock on the class

    public static void classBlock() {

    synchronized (Lock.class) {

    System.out.println("static block");

    sleepSilently(2000);

    }

    }

     

    private static void sleepSilently(long millis) {

    try {

    Thread.sleep(millis);

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

     

    public static void main(String[] args) {

     

    // object lock test

    new Thread() {

    @Override

    public void run() {

    lock.dynamicMethod();

    }

    }.start();

    new Thread() {

    @Override

    public void run() {

    lock.thisBlock();

    }

    }.start();

    new Thread() {

    @Override

    public void run() {

    lock.objectBlock();

    }

    }.start();

     

    sleepSilently(3000);

    System.out.println();

     

    // class lock test

    new Thread() {

    @Override

    public void run() {

    lock.staticMethod();

    }

    }.start();

    new Thread() {

    @Override

    public void run() {

    lock.classBlock();

    }

    }.start();

     

    }

    }

    上面的例子可以反映对一个锁竞争的现象,昆明java培训结合上面的例子,理解下面这两条,就可以很容易理解synchronized关键字的使用:

    非静态方法使用synchronized修饰,相当于synchronized(this)

    静态方法使用synchronized修饰,相当于synchronized(Lock.class)

    这篇文章分享的知识相比之前的文章信息量更大,如今昆明java培训希望大家抽时间来说学习一下。

    推荐文章

上一篇:javascript跑马灯悬停放大效果

下一篇:Java培训—hibernate修改数据变插入

最新开班日期  |  更多

Java--零基础全日制班

Java--零基础全日制班

开班日期:12/29

Java--零基础业余班

Java--零基础业余班

开班日期:12/29

Java--周末提升班

Java--周末提升班

开班日期:12/29

Java--零基础周末班

Java--零基础周末班

开班日期:12/29

  • 网址:http://km .java.tedu.cn      地址:昆明市官渡区春城路62号证券大厦附楼6楼
  • 课程培训电话:186 8716 1620      qq:2066486918    全国服务监督电话:400-827-0010
  • 服务邮箱 ts@tedu.cn
  • 2001-2016 达内国际公司(TARENA INTERNATIONAL,INC.) 版权所有 京ICP证08000853号-56