`

Java多线程发展简史(1)

阅读更多

引言

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

volatile、synchronized关键字?
竞争和同步?
锁机制?
线程安全问题?
线程池和队列?
好吧,请原谅我在这里卖的关子,其实这些都对,但是又不足够全面,如果我们这样来谈论Java多线程会不会全面一些:

模型:JMM(Java内存模型)和JCM(Java并发模型)
使用:JDK中的并发包
实践:怎样写线程安全的代码
除错:使用工具来分析并发问题
……
可是,这未免太死板了,不是么?

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

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

诞生

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

JDK 1.0

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

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

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

package com.jiaozg.thread;

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时不时地检查这个标志位。另外还有一种使用中断通信的方式,如下:
package com.jiaozg.thread;

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版本中,已经可以找到Thread和ThreadUsage这样的类,这也是线程模型中最核心的两个类。整个版本只包含了这样几个包:java.io、 java.util、java.net、java.awt和java.applet,所以说Java从一开始这个非常原始的版本就确立了一个持久的线程模型。

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

package com.jiaozg.thread;

import java.util.concurrent.atomic.AtomicInteger;

public class Atomicity {
	
	private static volatile int nonAtomicCounter = 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() {  
                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);  
	    }  

}

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

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

package com.jiaozg.thread;

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();  
	   
	    }  

}

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

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


ref:http://developer.51cto.com/art/201209/357617.htm
分享到:
评论

相关推荐

    狂神说Java-多线程课程全部代码.rar

    《狂神说Java-多线程课程全部代码》是一个涵盖了Java多线程和并发编程的实战教程资源。这个压缩包包含了一系列的示例代码(如demo01),旨在帮助开发者深入理解和掌握Java中的多线程技术及其在并发环境中的应用。 ...

    java核心技术第八版源代码(全)

    1.4 Java发展简史 1.5 关于Java的常见误解 第2章 Java程序设计环境 第3章 Java基本的程序设计程序 第4章 对象与类 第5章 继承 第6章 接口与内部类 第7章 图形程序设计 第8章 事件处理 第9章 Swing用户界面组件 第10...

    [java.核心技术.第八版].Core.Java..8th.Edition源代码 示例代码

    1.4 Java发展简史 1.5 关于Java的常见误解 第2章 Java 程序设计环境 第3章 Java基本的程序设计程序 第4章 对象与类 第5章 继承 第6章 接口与内部类 第7章 图形程序设计 第8章 事件处理 第9章 Swing用户界面组件 第...

    java 基础学习PPT

    Java是一种广泛使用的编程语言,以其平台独立性、面向对象的设计、简洁性、健壮性、安全性、解释性、多线程处理能力和动态特性著称。自1995年由Sun Microsystems公司发布以来,Java经历了多次重要更新,持续推动其...

    Java核心技术 卷I(原书第8版).Part1 pdf

    1.4 Java发展简史 1.5 关于Java的常见误解 第2章 Java程序设计环境 第3章 Java基本的程序设计程序 第4章 对象与类 第5章 继承 第6章 接口与内部类 第7章 图形程序设计 第8章 事件处理 第9章 Swing用户界面组件 第10...

    Core Java. Volume I. Fundamentals, 8th Edition JAVA核心技术1基础知识

    1.4 Java发展简史 1.5 关于Java的常见误解 第2章 Java程序设计环境 第3章 Java基本的程序设计程序 第4章 对象与类 第5章 继承 第6章 接口与内部类 第7章 图形程序设计 第8章 事件处理 第9章 Swing用户界面组件 第10...

    Java核心技术 卷I(原书第8版).part2 PDF

    1.4 Java发展简史 1.5 关于Java的常见误解 第2章 Java程序设计环境 第3章 Java基本的程序设计程序 第4章 对象与类 第5章 继承 第6章 接口与内部类 第7章 图形程序设计 第8章 事件处理 第9章 Swing用户界面组件 第10...

    大数据必学Java基础(一):Java体系结构、特性和优势

    Java是Sun公司开发的一种高级编程语言,具有跨平台、安全、面向对象、简单、高性能、分布式、多线程和健壮性等特性。Java的历史可以追溯到1991年,当时James Gosling率领的Sun公司工程师小组想要设计一种小型计算机...

    java初学者教程ppt

    Java的发展简史始于1991年,由SUN Microsystems公司的James Gosling、Bill Joe等人在开发名为Oak的软件时诞生。虽然最初目标并未成功,但 Oak 后来演变为Java,迅速获得了广泛的关注。Java因其特性被众多著名公司...

    java基础讲义

    Java的特性和优势包括自动内存管理(垃圾回收)、多线程支持、丰富的类库以及强大的异常处理机制,这些特性使得Java在各种应用场景中表现出色。 了解Java应用程序的运行机制至关重要。Java程序在运行时需要JRE...

    JAVA课设\课程设计说明书

    1. **JAVA语言发展简史** - JAVA起初名为Oak,由Sun公司的Green Team小组创建,最初设计用于嵌入式系统。 - 1994年,随着互联网的兴起,Oak被重新定位并更名为JAVA,适应网络环境,因其在网络上的优势迅速获得广泛...

    java基础培训.pdf(看这份就够了)

    1. Java语言发展简史:Java语言由Sun Microsystems公司于1995年推出,它的设计目的是能够在任何设备上运行,保证了“一次编写,到处运行”的特性。Java经历了多个版本的迭代,目前广泛使用的版本为Java SE 8和Java ...

    JAVA基础课程讲义

    JAVA的发展简史可追溯到1995年,由Sun Microsystems推出,其设计理念是“一次编写,到处运行”。JAVA之所以流行,是因为它具有跨平台性、安全性和高性能,同时提供了丰富的类库。JAVA分为多个版本,如JDK(Java ...

    java简介,关于Java入门方面的

    Java的发展简史表明,其名称来源于印度尼西亚的一个岛屿,同时又与程序员喜爱的咖啡相关。Java在互联网时代的成功主要归功于其跨平台特性,允许程序在不同操作系统上运行而无需重新编译。自1995年发布以来,Java已经...

    java基础知识大全(网上最全).docx

    Java 有着强大的多线程处理能力,多线程可以使程序有更好的交互性和实时性,并可以最大限度地利用多处理器系统。Java 为不同的操作系统实现了专门的多线程机制。 Java 简史: Java 技术起先是作为小型的电脑语言,...

    Java培训资料

    - **多线程**:Java内置了对多线程的支持,可以轻松地开发出高性能的应用程序。 - **动态性**:Java具有高度动态性,可以通过反射机制在运行时获取类的信息,并通过动态代理等方式实现动态绑定。 - **体系结构中立...

Global site tag (gtag.js) - Google Analytics