一、線(xiàn)程與進(jìn)程的區(qū)別
- 一個(gè)程序至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程至少有一個(gè)線(xiàn)程。
- 進(jìn)程是一個(gè)實(shí)體。每一個(gè)進(jìn)程都有它自己的地址空間和資源,一般情況下,包括文本區(qū)域(text region)、數(shù)據(jù)區(qū)域(data region)和堆棧(stack region)。
- 在一個(gè)程序中,這些獨(dú)立運(yùn)行的程序片段叫作“線(xiàn)程”(Thread)。
- 線(xiàn)程可以利用進(jìn)程所擁有的資源。
- 通常都是把進(jìn)程作為分配資源的基本單位,而把線(xiàn)程作為獨(dú)立運(yùn)行和獨(dú)立調(diào)度的基本單位。
二、多線(xiàn)程
多線(xiàn)程編程的目的,就是"最大限度地利用CPU資源",當(dāng)某一線(xiàn)程的處理不需要占用CPU而只和I/O等資源打交道時(shí),讓需要占用CPU資源的其它線(xiàn)程有機(jī)會(huì)獲得CPU資源。
三、Java中多線(xiàn)程的創(chuàng)建及啟動(dòng)
- 繼承Thread類(lèi),重寫(xiě)該類(lèi)的run()方法,使用start開(kāi)始執(zhí)行。
class MyThread extends Thread {
private int i = 0;
@Override
public void run() {
for (i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}
使用方法:
Thread myThread1 = new MyThread();
myThread1.start();
- 實(shí)現(xiàn)Runnable接口,并重寫(xiě)該接口的run()方法。然后以此實(shí)例作為T(mén)hread類(lèi)的target來(lái)創(chuàng)建Thread對(duì)象,并執(zhí)行。
class MyRunnable implements Runnable {
private int i = 0;
@Override
public void run() {
for (i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}
使用方法:
Runnable myRunnable = new MyRunnable();
Thread thread1 = new Thread(myRunnable);
thread1.start();
- 使用Callable和Future接口創(chuàng)建線(xiàn)程。具體是創(chuàng)建Callable接口的實(shí)現(xiàn)類(lèi),并實(shí)現(xiàn)clall()方法。并使用FutureTask類(lèi)來(lái)包裝Callable實(shí)現(xiàn)類(lèi)的對(duì)象,且以此FutureTask對(duì)象作為T(mén)hread對(duì)象的target來(lái)創(chuàng)建線(xiàn)程。
class MyCallable implements Callable<Integer> {
private int i = 0;
// 與run()方法不同的是,call()方法具有返回值
@Override
public Integer call() {
int sum = 0;
for (; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
sum += i;
}
return sum;
}
}
使用方法:
Callable<Integer> myCallable = new MyCallable(); // 創(chuàng)建MyCallable對(duì)象
FutureTask<Integer> ft = new FutureTask<Integer>(myCallable); //使用FutureTask來(lái)包裝MyCallable對(duì)象
Thread thread = new Thread(ft); //FutureTask對(duì)象作為T(mén)hread對(duì)象的target創(chuàng)建新的線(xiàn)程
thread.start(); //線(xiàn)程進(jìn)入到就緒狀態(tài)
FutureTask類(lèi)實(shí)際上是同時(shí)實(shí)現(xiàn)了Runnable和Future接口,由此才使得其具有Future和Runnable雙重特性。通過(guò)Runnable特性,可以作為T(mén)hread對(duì)象的target,而Future特性,使得其可以取得新創(chuàng)建線(xiàn)程中的call()方法的返回值。
Thread和Runnable之間關(guān)系
- Thread需要繼承,而Runnable只要實(shí)現(xiàn)接口就可以。在Java中,只能繼承一個(gè)類(lèi),但是可以實(shí)現(xiàn)多個(gè)接口。所以Runnable比Thread使用起來(lái)更方便。
- Runnable下更適合資源共享的情況。比如開(kāi)多個(gè)線(xiàn)程一起來(lái)賣(mài)票,票的數(shù)量是固定的,那么多個(gè)線(xiàn)程共享這么多數(shù)量的票。
所以多線(xiàn)程的情況下,盡量使用Runnable。
這一節(jié)就講到這里,在下一篇文章中會(huì)重點(diǎn)介紹線(xiàn)程安全。