java 多线程 归并_java多线程编程简介

1. Java多线程的实现方式

Java中提供如下三种方式的多线程实现方式,

a) 继承Thread类:实现run()方法。

b) 继承Runnable接口:实现run()方法,比起Thread类更加灵活,可以实现多个线程共享数据。

c) 继承Callable接口:实现call()方法,比起Thread和Runnable,可以获取各个线程的返回值。

代码样例如下(具体的演示样例请参见multithread项目中的demo1),

// BaseThread继承自Thread类

BaseThread t1 = new BaseThread("Thread-1");

BaseThread t2 = new BaseThread("Thread-2");

t1.start();

t2.start();

// BaseRunable继承自Runnable接口,线程r1/r2共享run对象的数据

BaseRunable run = new BaseRunable();

Thread r1 = new Thread(run, "Thread-run-1");

Thread r2 = new Thread(run, "Thread-run-2");

r1.start();

r2.start();

// BaseCallback继承自Callable接口,在执行完毕后可以获取执行结果

ExecutorService exec = Executors.newCachedThreadPool();

Future result = exec.submit(new BaseCallback(100));

while(!result.isDone()){

App.sleep(1);

}

try {

App.logMessage("result: " + result.get());

} catch (Exception e) {

e.printStackTrace();

}

exec.shutdown();

2. Java多线程的同步Synchronized

为了控制多个线程对同一代码区的访问,Java语言提供了Synchronized关键字给对象、方法或者代码块进行加锁,加了锁的代码块在同一时间只能允许一个线程执行。

在如下的类中run()方法中加了Synchronized关键字,这将会使得第一个进入run()方法的线程打印完所有的count数字(从10到1),而后进入的其它线程将不会输出任何信息(因为count为0),注:假设所有线程使用同一个run对象初始化。

public class BaseRunableSync implements Runnable {

private int count = 10;

public synchronized void run() {

for( ; count>0; count--) {

App.logMessage("count=" + count);

}

}

}

具体的演示样例请参见multithread项目中的demo2。

3. Java多线程的阻塞(Sleep/Wait)

在多线程编程中,很多时候不仅需要利用多线程充分使用资源,也要需要释放资源。Thread.Sleep和Object.wait就是在线程运行时主动释放CPU资源或者同步锁资源。

Thread.Sleep:当前线程进入阻塞模式,释放CPU资源,但是不释放同步锁。

Object.Wait:当前线程进入阻塞模式,释放CPU资源并释放同步锁。注意Object.wait必须和Synchronized同步配合使用,否则因为没有同步锁释放而导致抛异常。

具体的演示样例请参见multithread项目中的demo3,分别有如下的演示,

a)  runnable + synchronized :同步区没有任何阻塞

b) runnable + synchronized + sleep:同步区加sleep,线程被阻塞到等待池

c)  runnable + synchronized + wait:同步区加wait,线程被阻塞到等待池

4. Java多线程的合并(join)

Java程序起来后,有一个main的主线程,其它线程都是从该主线程诞生出子线程,如果子线程运行时间比较长,很有可能的情况是,主线程已经结束但子线程还在运行。

为了能够让主线程能够等待子线程的结束,可以使用thread.join()方法,使得当前线程阻塞到等待池,一直等待子线程执行完毕,

public class App {

public static void main(String[] args) throws InterruptedException {

App.logMessage("start...");

BaseRunable run = new BaseRunable();

Thread r1 = new Thread(run);

Thread r2 = new Thread(run);

r1.start();

r2.start();

// add the join method, which wait for r1/r2 to be finished

r1.join();

r2.join();

App.logMessage("the end.");

}

}

上述代码中,如果没有r1.join()和r2.join(),主线程很有可能在r1和r2执行完之前就已经结束。

具体代码样例请参见multithread项目中的demo4。

5. Java多线程的死锁

多线程中,如果执行代码有多个资源锁,如果执行顺序不当,就会形成死锁。比如两个子线程,互相握有对方需要的对象锁并不释放,则会形成死锁。

public class DeadlockRunable implements Runnable {

private Object lock1 = new Object();

private Object lock2 = new Object();

private Boolean bLockFlag = Boolean.FALSE;

public void run() {

bLockFlag = !bLockFlag;

if(bLockFlag){

synchronized(lock1){

App.logMessage("lock1 is locked...");

App.sleep(2);

synchronized(lock2){

App.logMessage("lock2 is locked...");

}

}

}

else {

synchronized(lock2){

App.logMessage("lock2 is locked...");

App.sleep(2);

synchronized(lock1){

App.logMessage("lock1 is locked...");

}

}

}

}

}

一个死锁代码样例请参见multithread项目中的demo5。

6. Java多线程的状态

Java多线程有如下几种状态,

新建(NEW)

就绪/可运行/在运行(RUNNABLE)

阻塞(BLOCKED)

等待(WAITING/TIMED_WAITING)

结束(TERMINATED)

线程在各个状态的流转图见如下,

thread_status-300x169.png

代码样例

git clone git@git.oschina.net:pphh/tools.git

上述代码样例在文件路径tools\java\multithread中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值