1.Thread
/**
- 繼承Thread類創(chuàng)建線程類
- (1)定義Thread類的子類犹芹,重寫該類的run方法崎页,該run方法的方法體就代表了線程要完成的任務(wù)。
- (2)創(chuàng)建Thread子類的實(shí)例腰埂,即創(chuàng)建了線程對(duì)象飒焦。
- (3)調(diào)用線程對(duì)象的start()方法來啟動(dòng)該線程。
*/
package thread;
public class Thread_Test extends Thread{
private int ticketnum = 10;
//重寫run方法屿笼,run方法的方法體就是現(xiàn)場(chǎng)執(zhí)行體
public void run() {
for(int i=0; i<20;i++){
if (this.ticketnum > 0) {
ticketnum--;
System.out.println("總共10張,賣掉1張牺荠,剩余" + ticketnum);
}
}
}
public static void main(String[] args)
{
new Thread_Test().start();
new Thread_Test().start();
new Thread_Test().start();
//實(shí)際上是賣掉了30張車票
}
}
輸出:
總共10張,賣掉1張,剩余9
總共10張,賣掉1張驴一,剩余8
總共10張,賣掉1張休雌,剩余7
總共10張,賣掉1張,剩余6
總共10張,賣掉1張肝断,剩余9
總共10張,賣掉1張杈曲,剩余8
總共10張,賣掉1張,剩余7
總共10張,賣掉1張胸懈,剩余6
總共10張,賣掉1張鱼蝉,剩余5
總共10張,賣掉1張,剩余5
總共10張,賣掉1張箫荡,剩余4
總共10張,賣掉1張,剩余9
總共10張,賣掉1張渔隶,剩余3
總共10張,賣掉1張羔挡,剩余2
總共10張,賣掉1張洁奈,剩余1
總共10張,賣掉1張,剩余0
總共10張,賣掉1張绞灼,剩余4
總共10張,賣掉1張利术,剩余3
總共10張,賣掉1張,剩余2
總共10張,賣掉1張低矮,剩余1
總共10張,賣掉1張印叁,剩余0
總共10張,賣掉1張,剩余8
總共10張,賣掉1張军掂,剩余7
總共10張,賣掉1張轮蜕,剩余6
總共10張,賣掉1張,剩余5
總共10張,賣掉1張蝗锥,剩余4
總共10張,賣掉1張跃洛,剩余3
總共10張,賣掉1張,剩余2
總共10張,賣掉1張终议,剩余1
總共10張,賣掉1張汇竭,剩余0
2.Runnable
/**
- 通過Runnable接口創(chuàng)建線程類
- (1)定義runnable接口的實(shí)現(xiàn)類,重寫該接口的run()方法穴张,該run()方法的方法體是該線程的線程執(zhí)行體细燎。
- (2)創(chuàng)建Runnable實(shí)現(xiàn)類的實(shí)例,并依此實(shí)例作為Thread的Runnable target來創(chuàng)建Thread對(duì)象皂甘,
- 該Thread對(duì)象才是真正的線程對(duì)象玻驻。
- (3)調(diào)用線程對(duì)象的start()方法來啟動(dòng)該線程。
*/
package thread;
public class Runnable_Test implements Runnable {
private int ticketnum = 10;
public void run() {
for(int i=0; i<20;i++){
if (this.ticketnum > 0) {
ticketnum--;
System.out.println("總共10張,"+Thread.currentThread().getName()+"賣掉1張叮贩,剩余" + ticketnum);
}
}
}
public static void main(String[] args) {
/*因?yàn)镽unnable_Test是New了一次击狮,使用的是同一個(gè)Runnable_Test,
可以達(dá)到資源的共享益老。最終只賣出10張車票*/
Runnable_Test rtt = new Runnable_Test();
//使用三個(gè)線程調(diào)用
new Thread(rtt, "賣票線程1").start();
new Thread(rtt, "賣票線程2").start();
new Thread(rtt, "賣票線程3").start();
}
}
輸出:
總共10張,賣票線程1賣掉1張彪蓬,剩余8
總共10張,賣票線程3賣掉1張,剩余7
總共10張,賣票線程2賣掉1張捺萌,剩余8
總共10張,賣票線程3賣掉1張档冬,剩余5
總共10張,賣票線程1賣掉1張,剩余6
總共10張,賣票線程3賣掉1張桃纯,剩余3
總共10張,賣票線程2賣掉1張酷誓,剩余4
總共10張,賣票線程3賣掉1張,剩余1
總共10張,賣票線程1賣掉1張态坦,剩余2
總共10張,賣票線程2賣掉1張盐数,剩余0
3.Callable
/**
- 通過Callable和Future創(chuàng)建線程
- (1)創(chuàng)建Callable接口的實(shí)現(xiàn)類,并實(shí)現(xiàn)call()方法伞梯,該call()方法將作為線程執(zhí)行體玫氢,并且有返回值帚屉。
- (2)創(chuàng)建Callable實(shí)現(xiàn)類的實(shí)例,創(chuàng)建FutureTask來包裝Callable對(duì)象漾峡,
- 該FutureTask對(duì)象封裝了該Callable對(duì)象的call()方法的返回值攻旦。
- (3)使用FutureTask對(duì)象作為Thread對(duì)象的Runnable target創(chuàng)建并啟動(dòng)新線程。
- (4)調(diào)用FutureTask對(duì)象的get()方法來獲得子線程執(zhí)行結(jié)束后的返回值
*/
package thread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Callable_Test implements Callable<String> {
private int ticketnum = 10;
@Override
public String call() throws Exception {
int t = 0;
for (int i = 0; i < 20; i++) {
if (this.ticketnum > 0) {
ticketnum--;
t++;
System.out.println(Thread.currentThread().getName() + "總共10張,賣掉1張生逸,剩余" + ticketnum);
}
}
return t + "";
}
public static void main(String[] args) {
Callable_Test ctt = new Callable_Test();
FutureTask<String> ft1 = new FutureTask<>(ctt);
FutureTask<String> ft2 = new FutureTask<>(ctt);
FutureTask<String> ft3 = new FutureTask<>(ctt);
Thread th1 = new Thread(ft1, "線程1");
Thread th2 = new Thread(ft2, "線程2");
Thread th3 = new Thread(ft3, "線程3");
th1.start();
th2.start();
th3.start();
try {
System.out.println(th1.getName() + "的返回值:" + ft1.get());
System.out.println(th2.getName() + "的返回值:" + ft2.get());
System.out.println(th3.getName() + "的返回值:" + ft3.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
輸出:
線程2總共10張,賣掉1張牢屋,剩余7
線程2總共10張,賣掉1張,剩余6
線程2總共10張,賣掉1張槽袄,剩余5
線程2總共10張,賣掉1張烙无,剩余4
線程2總共10張,賣掉1張,剩余3
線程2總共10張,賣掉1張掰伸,剩余2
線程1總共10張,賣掉1張皱炉,剩余7
線程3總共10張,賣掉1張,剩余7
線程1總共10張,賣掉1張狮鸭,剩余0
線程2總共10張,賣掉1張合搅,剩余1
線程1的返回值:2
線程2的返回值:7
線程3的返回值:1
創(chuàng)建線程的三種方式的對(duì)比:
采用實(shí)現(xiàn)Runnable、Callable接口的方式創(chuàng)見多線程時(shí):
優(yōu)勢(shì):
線程類只是實(shí)現(xiàn)了Runnable接口或Callable接口歧蕉,還可以繼承其他類灾部。
Callable有返回值
在這種方式下,多個(gè)線程可以共享同一個(gè)target對(duì)象惯退,所以非常適合多個(gè)相同線程來處理同一份資源的情況赌髓,
從而可以將CPU、代碼和數(shù)據(jù)分開催跪,形成清晰的模型锁蠕,較好地體現(xiàn)了面向?qū)ο蟮乃枷搿?br>
劣勢(shì):
編程稍微復(fù)雜,如果要訪問當(dāng)前線程懊蒸,則必須使用Thread.currentThread()方法荣倾。
使用繼承Thread類的方式創(chuàng)建多線程時(shí):
優(yōu)勢(shì):
編寫簡(jiǎn)單,如果需要訪問當(dāng)前線程骑丸,則無需使用Thread.currentThread()方法舌仍,直接使用this即可獲得當(dāng)前線程。
劣勢(shì):
線程類已經(jīng)繼承了Thread類通危,不能再繼承其他父類铸豁。