一、創(chuàng)建線程的兩種方式:
1、繼承thread類(lèi);重寫(xiě)run方法。(單繼承,直接寫(xiě)業(yè)務(wù)邏輯)
public class Demo1 extends Thread{
@Override
? ? ? public void run{
? ? ? ? ? ? ? ? ?for(int=i; i<100; i++){
? ? ? ? ? ? ? ? ? ?system.out.println(“自定義線程:”+i);
? ? ? ? ? ? ? ?}
? ? ? ? ?}
}
2、實(shí)現(xiàn)Runnable接口,運(yùn)行run方法來(lái)實(shí)現(xiàn)線程。
class ?Demo2 implement Runnable{
? ? ? ? ?@Override
? ? ? ? public void run() {
? ? ? ? ? ? ? ? ? while (true) {
? ? ? ? ? ? ? ? ? ? ? ? ? ?synchronized ("鎖") {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (ticket > 0) {
? ? ? ? ? ? ? ? ? ? ? ? System.out.println(Thread.currentThread().getName() + ":賣(mài)出了第" + ticket + "張");
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ticket--;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Thread.sleep(100);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?} catch (InterruptedException e) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?} else {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? System.out.println("票買(mǎi)完了");
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?break;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? ? ? ? }
public class TestSaleTicket01 { //利用start來(lái)啟動(dòng)線程
? ? ? ? ? ? ? ? ? ? ? ?public static void main(String[] args) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Demo2 run = new Demo2();
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?new Thread(run,"yi").start();
? ? ? ? ? ? ? ? ? ? ? ? ? ? new Thread(run,"er").start();
? ? ? ? ? ? ? ? ? ? ? ? ? ? new Thread(run,"san").start();
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? }
}
二、多線程:
? ? ? 1、多線程的作用:
1)發(fā)揮多核cpu的優(yōu)勢(shì);多核CPU讓多段邏輯同時(shí)工作,實(shí)現(xiàn)多線程。
2)防止阻塞;多條線程運(yùn)行時(shí),有一個(gè)線程讀取數(shù)據(jù)阻塞,不會(huì)影響其他任務(wù)的執(zhí)行。
3)便于建模。把一個(gè)大任務(wù)A分解成幾個(gè)小任務(wù),分別建立程序模型,并通過(guò)多線程分別運(yùn)行這幾個(gè)任務(wù)。
2、創(chuàng)建線程:1)繼承thread類(lèi) ?2)實(shí)現(xiàn)Runnable接口,建議使用第二種方式,因?yàn)閷?shí)現(xiàn)接口的的方式比繼承類(lèi)的方式更加靈活,也能減少程序之間的耦合度,面向接口也是設(shè)計(jì)模式的6大原則的核心。
3、start()方法和run()方法的區(qū)別:
線程開(kāi)啟用的是start方法,只有調(diào)用了start 的方法,才會(huì)表現(xiàn)出多線程的特性,不同線程的run()方法中的代碼塊交替執(zhí)行。如果只調(diào)用run方法,那么代碼塊還是同步執(zhí)行的,必須等待一個(gè)線程中的代碼執(zhí)行完畢后,另一個(gè)線程才能執(zhí)行其run方法里面的代碼。
4、Runnable接口和Callable接口的區(qū)別
Runnable接口中的run()方法返回值是void,它做的事情只是單純的執(zhí)行方法。
但callable接口中的call()方法是有返回值的,是一個(gè)泛型,和future、futuretask配合使用可以獲取異步執(zhí)行的結(jié)果。Callable(產(chǎn)生結(jié)果)功能更強(qiáng)大,被線程執(zhí)行后,可以返回值;Future(獲取結(jié)果)可以拿到異步執(zhí)行任務(wù)的返回值。
例如:當(dāng)某條線程執(zhí)行時(shí),我們期望的數(shù)據(jù)是否已經(jīng)復(fù)制完畢無(wú)法得知時(shí);如果用Runnable只能等待線程執(zhí)行完畢,而Callable+future可以獲取多線程運(yùn)行結(jié)果,可以在等待時(shí)間太長(zhǎng)沒(méi)有獲取到結(jié)果需要數(shù)據(jù)時(shí)取消該線程的任務(wù)。