java

位置:IT落伍者 >> java >> 浏览文章

Java多线程发展简史


发布日期:2018年09月18日
 
Java多线程发展简史

引言

首先问这样一个问题如果提到Java多线程编程你会想到什么?

volatilesynchronized关键字?

竞争和同步?

锁机制?

线程安全问题?

线程池和队列?

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

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

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

另外还有一点要说是我希望通过大量的实例代码来说明这些事情Linus说Talk is cheap show me the code下文涉及到的代码我已经上传可以在此打包下载

诞生

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

JDK

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

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

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

publicclassInterruptCheckextendsThread{

@Override

publicvoidrun(){

Systemoutprintln(start);

while(true)

if(ThreadcurrentThread()isInterrupted())

break;

Systemoutprintln(whileexit);

}

publicstaticvoidmain(String[]args){

Threadthread=newInterruptCheck();

threadstart();

try{

sleep();

}catch(InterruptedExceptione){

}

threadinterrupt();

}

}

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

publicclassInterruptWaitextendsThread{

publicstaticObjectlock=newObject();

@Override

publicvoidrun(){

Systemoutprintln(start);

synchronized(lock){

try{

lockwait();

}catch(InterruptedExceptione){

Systemoutprintln(ThreadcurrentThread()isInterrupted());

ThreadcurrentThread()interrupt();//setinterruptflagagain

Systemoutprintln(ThreadcurrentThread()isInterrupted());

eprintStackTrace();

}

}

}

publicstaticvoidmain(String[]args){

Threadthread=newInterruptWait();

threadstart();

try{

sleep();

}catch(InterruptedExceptione){

}

threadinterrupt();

}

}

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

在比较稳定的JDK 版本中已经可以找到Thread和ThreadUsage这样的类这也是线程模型中最核心的两个类整个版本只包含了这样几个包javaio javautiljavaawt和javaapplet所以说Java从一开始这个非常原始的版本就确立了一个持久的线程模型

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

importncurrentatomicAtomicInteger;

publicclassAtomicity{

privatestaticvolatileintnonAtomicCounter=;

privatestaticvolatileAtomicIntegeratomicCounter=newAtomicInteger();

privatestaticinttimes=;

publicstaticvoidcaculate(){

times++;

for(inti=;i<;i++){

newThread(newRunnable(){

@Override

publicvoidrun(){

nonAtomicCounter++;

atomicCounterincrementAndGet();

}

})start();

}

try{

Threadsleep();

}catch(InterruptedExceptione){

}

}

publicstaticvoidmain(String[]args){

caculate();

while(nonAtomicCounter==){

nonAtomicCounter=;

atomicCounterset();

caculate();

}

Systemoutprintln(Nonatomiccounter:+times+:

+nonAtomicCounter);

Systemoutprintln(Atomiccounter:+times+:+atomicCounter);

}

}

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

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

publicclassLock{

privatestaticObjecto=newObject();

staticLocklock=newLock();

//lockondynamicmethod

publicsynchronizedvoiddynamicMethod(){

Systemoutprintln(dynamicmethod);

sleepSilently();

}

//lockonstaticmethod

publicstaticsynchronizedvoidstaticMethod(){

Systemoutprintln(staticmethod);

sleepSilently();

}

//lockonthis

publicvoidthisBlock(){

synchronized(this){

Systemoutprintln(thisblock);

sleepSilently();

}

}

//lockonanobject

publicvoidobjectBlock(){

synchronized(o){

Systemoutprintln(dynamicblock);

sleepSilently();

}

}

//lockontheclass

publicstaticvoidclassBlock(){

synchronized(Lockclass){

Systemoutprintln(staticblock);

sleepSilently();

}

}

privatestaticvoidsleepSilently(longmillis){

try{

Threadsleep(millis);

}catch(InterruptedExceptione){

eprintStackTrace();

}

}

publicstaticvoidmain(String[]args){

//objectlocktest

newThread(){

@Override

publicvoidrun(){

lockdynamicMethod();

}

}start();

newThread(){

@Override

publicvoidrun(){

lockthisBlock();

}

}start();

newThread(){

@Override

publicvoidrun(){

lockobjectBlock();

}

}start();

sleepSilently();

Systemoutprintln();

//classlocktest

newThread(){

@Override

publicvoidrun(){

lockstaticMethod();

}

}start();

newThread(){

@Override

publicvoidrun(){

lockclassBlock();

}

}start();

}

}

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

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

静态方法使用synchronized修饰相当于synchronized(Lockclass)               

上一篇:超线程多核心下Java多线程编程分析

下一篇:23种设计模式的Java版--Singleton(单例)