一、什么是線程
線程是獨(dú)立調(diào)度和分派的基本單位,它被包含在進(jìn)程之中,是進(jìn)程中的實(shí)際運(yùn)作單位
二、什么是進(jìn)程
進(jìn)程是一個(gè)具有一定獨(dú)立功能的程序關(guān)于某個(gè)數(shù)據(jù)集合的一次運(yùn)行活動(dòng)。它是操作系統(tǒng)動(dòng)態(tài)執(zhí)行的基本單元,在傳統(tǒng)的操作系統(tǒng)中,進(jìn)程既是基本的分配單元,也是基本的執(zhí)行單元。
一個(gè)進(jìn)程可以包含有多個(gè)線程
三、java多線程的實(shí)現(xiàn)方式
1、實(shí)現(xiàn)方法簡(jiǎn)述
| 方法一 | 方法二 |
|---|---|
| 繼承Thread類,重寫run()方法,執(zhí)行start()方法啟動(dòng)多線程 | 普通類實(shí)現(xiàn)Runnable接口,重寫run()方法,啟動(dòng)時(shí),使用Thread類裝載線程對(duì)象,最后使用start方法啟動(dòng)(方法二比較常用,因?yàn)閖ava類是單繼承的,盡量使用接口) |
2、實(shí)例
方法一:繼承Thread類,重寫run()方法,執(zhí)行start()方法啟動(dòng)多線程
/**
* @description 線程測(cè)試類,使用第一種實(shí)現(xiàn)方式
* 第一步 繼承Thread類
* 第二步重寫run()方法
* 第三步執(zhí)行start()方法啟動(dòng)多線程
* @version 1.0
* @author manyu
* @address www.mpmanyu.com
* @update 2021年3月26日 下午10:51:59
*
*/
public class TestThread2 extends Thread {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("i="+i);
};
}
}
TestThread1類自己建立一個(gè),內(nèi)容相同
創(chuàng)建進(jìn)程啟動(dòng)類
/**
* @description 測(cè)試線程,同時(shí)運(yùn)行TestThread1 ,TestThread2 兩個(gè)類的對(duì)象
* @version 1.0
* @author manyu
* @address www.mpmanyu.com
* @update 2021年3月26日 下午11:05:11
*
*/
public class ThreadWindows {
public static void main(String[] args) {
//第一個(gè)線程對(duì)象
TestThread1 test1 = new TestThread1();
//第二個(gè)線程對(duì)象
TestThread2 test2 = new TestThread2();
//同時(shí)啟動(dòng)test1 與 test2
test1.start();
test2.start();
}
}
執(zhí)行結(jié)果如下
i=9
i=10
j=0
i=11
j=1
i=12
i=13
i=14
.......
方法二:普通類實(shí)現(xiàn)Runnable接口,使用Thread類裝載線程對(duì)象,最后使用start方法啟動(dòng)(方法二比較常用,因?yàn)閖ava類是單繼承的,盡量使用接口)
代碼如下:
建立ThreadDemo3 ThreadDemo4兩個(gè)類,內(nèi)容相同
/**
* @ClassName: ThreadDemo3
* @Description: 使用第二種方式啟動(dòng)線程
* 實(shí)現(xiàn)Runnable接口,裝載線程,啟動(dòng)線程
* @author: manyu
* @date: 2021年3月27日 上午10:43:10
*/
public class ThreadDemo3 implements Runnable{
/* (non-Javadoc)
* @see java.lang.Runnable#run()
* 使用第二種方式啟動(dòng)線程
*/
@Override
public void run() {
for(int i =0;i<1000;i++) {
System.out.println("第二種方式啟動(dòng) i="+i);
Thread.yield();
}
}
}
建立啟動(dòng)類
/**
* @ClassName: ThreadWindow
* @Description: 使用第二種方式啟動(dòng)多線程
* @author: manyu
* @date: 2021年3月27日 上午8:06:56
*/
public class ThreadWindow2 {
/**
* @Title: main
* @Description: 使用第二種方式啟動(dòng)線程
* @param args
* @author manyu
* @update 2021年3月27日上午8:06:56
*/
public static void main(String[] args) {
//創(chuàng)建thread3對(duì)象
ThreadDemo3 threadDemo3 = new ThreadDemo3();
Thread thread3 = new Thread(threadDemo3);
thread3.start();
//創(chuàng)建thread4對(duì)象
ThreadDemo4 threadDemo4 = new ThreadDemo4();
Thread thread4 = new Thread(threadDemo4);
thread4.start();
}
}
四、java線程安全問題
1、線程安全問題出現(xiàn)的前提
當(dāng)多個(gè)線程操作同一共享數(shù)據(jù)的時(shí)候,就會(huì)產(chǎn)生線程安全問題。
2、如何解決線程安全問題
給共享數(shù)據(jù)加鎖,使用synchronized (類.class)
例如:賣票小案例
售票系統(tǒng)類說明:TicketDemo類是賣票的線程類,共200張票,不同的站點(diǎn)進(jìn)行賣票,假設(shè)完成一次售票需要10ms時(shí)間。
/**
* @ClassName: TicketDemo
* @Description: 購票軟件實(shí)例 共有200張票,n個(gè)售票窗口進(jìn)行售票
* @author: manyu
* @address: www.mpmanyu.com
* @date: 2021年3月27日 下午4:04:02
*/
public class TicketDemo implements Runnable {
private static int TICKETNUM = 200; //一共有200張票
@Override
public void run() {
try {
for(int i = 2000; i>0;i--) {
//必須給售票的整個(gè)過程加鎖,保證一個(gè)線程處理完成后才能后下一個(gè)線程進(jìn)行賣票
synchronized (TicketDemo.class) {
if(TICKETNUM>0) {
TICKETNUM--;
System.out.println("剩余票數(shù)="+TICKETNUM);
Thread.sleep(10);//假設(shè)一次售票需要10ms
}
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
窗口類說明:WindowThread類是窗口類,模擬多個(gè)窗口同時(shí)售票。如果要所有的售票點(diǎn)能夠正常售票,不要超賣。造成 售票量>總票量(200),必須在給整個(gè)的售賣過程加鎖。
/**
* @ClassName: WindowThread
* @Description: 售票測(cè)試的窗口測(cè)試程序
* @author: manyu
* @address: www.mpmanyu.com
* @date: 2021年3月27日 下午4:09:46
*/
public class WindowThread {
public static void main(String[] args) {
//窗口1
TicketDemo win1 = new TicketDemo();
Thread win1Thread = new Thread(win1);
//窗口2
TicketDemo win2 = new TicketDemo();
Thread win2Thread = new Thread(win2);
//窗口3
TicketDemo win4 = new TicketDemo();
Thread win4Thread = new Thread(win4);
//窗口4
TicketDemo win5 = new TicketDemo();
Thread win5Thread = new Thread(win5);
//開始售票
win1Thread.start();
win2Thread.start();
win4Thread.start();
win5Thread.start();
}
}
3、run()與start()方法的區(qū)別
run()方法相當(dāng)于調(diào)用普通方法,它是順序執(zhí)行,實(shí)際還是單線程;
start()方法真正啟動(dòng)線程,