轉(zhuǎn)發(fā)請(qǐng)注明出處:
安卓猴的博客(http://sunjiajia.com)
本節(jié)課程將學(xué)習(xí)以下內(nèi)容:
- 進(jìn)程和線(xiàn)程的關(guān)系
- 多線(xiàn)程程序運(yùn)行模式
- 定義線(xiàn)程的方法
- 控制線(xiàn)程的常用函數(shù)
- 多線(xiàn)程的數(shù)據(jù)安全
- 同步線(xiàn)程的方法
- 深入synchronized關(guān)鍵字
進(jìn)程和線(xiàn)程的關(guān)系
多進(jìn)程:
在操作系統(tǒng)中能(同時(shí))運(yùn)行多個(gè)任務(wù)(程序)汽抚。
多線(xiàn)程:
在同一個(gè)應(yīng)用程序中有多個(gè)順序流(同時(shí))進(jìn)行。
多線(xiàn)程程序運(yùn)行模式
線(xiàn)程的執(zhí)行過(guò)程:
定義線(xiàn)程的方法
方法1:
定義一個(gè)線(xiàn)程類(lèi)物独,它繼承類(lèi)Thread并重寫(xiě)其中的方法run()肃廓,方法run()稱(chēng)為線(xiàn)程體般妙;
方法2:
提供一個(gè)實(shí)現(xiàn)接口Runnable的類(lèi)作為線(xiàn)程的目標(biāo)對(duì)象阻逮,在初始化一個(gè)Thread類(lèi)或者Thread子類(lèi)的線(xiàn)程對(duì)象時(shí)容诬,把目標(biāo)對(duì)象傳遞給這個(gè)線(xiàn)程實(shí)例娩梨,由該目標(biāo)對(duì)象提供線(xiàn)程體。
例子1:
1.新建一個(gè)FirstThread.java的源文件:
class FirstThread extends Thread {
public void run(){
for (int i = 0; i < 100; i++) {
System.out.println("FirstThread-->" + i);
}
}
}
2.新建一個(gè)Demo01.java的源文件:
class Demo01 {
public static void main(String[] args) {
// 生成線(xiàn)程類(lèi)的對(duì)象
FirstThread thread01 = new FirstThread();
// 啟動(dòng)線(xiàn)程
thread01.start();
for (int i = 0; i < 100; i++) {
System.out.println("main-->" + i);
}
}
}
3.新建一個(gè)RunnableImpl.java的源文件:
class RunnableImpl implements Runnable {
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("Runnable-->" + i);
}
}
}
4.新建一個(gè)Demo02.java的源文件:
class Demo02 {
public static void main(String[] args) {
// 生成一個(gè)Runnable接口實(shí)現(xiàn)類(lèi)的對(duì)象
RunnableImpl ri = new RunnableImpl();
// 生成一個(gè)Thread對(duì)象览徒,并將Runnable接口實(shí)現(xiàn)類(lèi)的對(duì)象作為參數(shù)傳遞進(jìn)去
Thread t = new Threadj(ri);
t.start();
// 打印當(dāng)前線(xiàn)程的優(yōu)先級(jí)
// 默認(rèn)優(yōu)先級(jí)是5狈定,最大優(yōu)先級(jí)是10,最小優(yōu)先級(jí)是1习蓬。
// 線(xiàn)程的優(yōu)先級(jí)越高纽什,它執(zhí)行的概率就越大。
System.out.println(t.getPriority());
t.setPriority(Thread.MAX_PRIORITY);
}
}
控制線(xiàn)程的常用函數(shù)
中斷線(xiàn)程:
Thread.sleep(2000);線(xiàn)程睡眠2000毫秒友雳。
Thread.yield();線(xiàn)程自動(dòng)讓出cpu稿湿。
設(shè)置線(xiàn)程的優(yōu)先級(jí):
getPriority();
setPriority();
多線(xiàn)程的數(shù)據(jù)安全
同步線(xiàn)程的方法
- 多線(xiàn)程共用同一份數(shù)據(jù)的時(shí)候,會(huì)出現(xiàn)某種錯(cuò)誤押赊;
- 因此需要在同步線(xiàn)程饺藤。
例子2:
1.新建一個(gè)MyThread.java的源文件:
class MyThread implements Runnable {
int i = 100;
public void run(){
while (true) {
// 同步代碼塊
// 解決多線(xiàn)程共用同一份數(shù)據(jù)時(shí)出現(xiàn)錯(cuò)誤的問(wèn)題
synchronized (this) {
System.out.println(Thread.currentThread().getName() + i);
i--;
Thread.yield();
if (i < 0) {
break;
}
}
}
}
}
2.新建一個(gè)Demo03.java的源文件:
class Demo03 {
public static void main(String[] args) {
MyThread myThread = new MyThread();
// 生成兩個(gè)Thread對(duì)象,但是這兩個(gè)對(duì)象共用同一個(gè)線(xiàn)程體
Thread t1 = new Thread(myThread);
Thread t2 = new Thread(myThread);
// 每一個(gè)線(xiàn)程都有名字流礁,可以通過(guò)Thread對(duì)象的setName()方法設(shè)置
t1.setName("線(xiàn)程a");
t2.setName("線(xiàn)程b");
// 分別啟動(dòng)兩個(gè)線(xiàn)程
t1.start();
t2.start();
}
}
深入synchronized關(guān)鍵字
同步鎖涕俗,它鎖住的是對(duì)象。
如果一個(gè)線(xiàn)程獲得了一個(gè)對(duì)象的同步鎖神帅,那么這個(gè)對(duì)象上面的所有的其它的同步代碼都是不能夠被其它線(xiàn)程執(zhí)行的再姑,都需要等待同步鎖被釋放后,才能夠進(jìn)行找御。
例子3:
1.新建一個(gè)名為Service.java的源文件:
class Service {
public voi fun1 () {
synchronized (this) {
try {
Thread.sleep(3000);
} catch (Exception e) {
System.out.println(e);
}
System.out.println("fun1");
}
}
// fun2是一個(gè)同步方法元镀,和fun1中的同步代碼塊功能一樣
public synchronized voi fun2 () {
System.out.println("fun2");
}
}
2.新建一個(gè)名為MyThread1.java的源文件:
class MyThread1 implements Runnable {
private Service service;
public MyThread1 (Service service) {
this.service = service;
}
public void run () {
service.fun1();
}
}
3.新建一個(gè)名為MyThread2.java的源文件:
class MyThread2 implements Runnable {
private Service service;
public MyThread2 (Service service) {
this.service = service;
}
public void run () {
service.fun2();
}
}
4.新建一個(gè)名為Demo04.java的源文件:
class Demo04 {
public static void main(String[] args) {
Service service = new Service();
Thread t1 = new Thread(new MyThread1(service));
Thread t2 = new Thread(new MyThread2(service));
t1.start();
t2.start();
}
}