在java中5 % 3_Java基础5
Java多線程:
進程:進行中的程序
線程:就是進程中一個負責(zé)程序執(zhí)行的控制單元(執(zhí)行單元)
一個進程中可以多執(zhí)行路徑,稱之為多線程
一個進程至少一個線程
開啟多個線程是為了同時運行多部分代碼
每個線程都有自己運行的內(nèi)容,這個內(nèi)容成為線程要執(zhí)行的任務(wù)
多線程的好處:解決了多部分同時運行的問題
多線程的弊端:線程太多回到效率的降低
其實應(yīng)用程序的執(zhí)行都是CPU在做著快速的切換完成的,這個切換是隨機的
JVM啟動時就啟動了多個線程,至少有兩個線程
1.執(zhí)行main函數(shù)的線程
該線程的任務(wù)代碼都定義在main函數(shù)里
2.負責(zé)垃圾回收的線程
如何創(chuàng)建一個線程:
方式一:繼承Thread類
步驟:
1.創(chuàng)建一個類繼承Thread類
2.重寫Thread的run方法//重寫run方法
3.直接創(chuàng)建Thread類的子類對象C創(chuàng)建線程
4.調(diào)用start方法開啟線程并調(diào)用線程的任務(wù)run方法執(zhí)行
class Demo extends Thread
{
private String name = "弟鴿";
Demo(String name)
{
super(name);
//this.name = name;
}
public void run(){
for(int i=1;i<10;i++)
{
for(long j= -199999999;j<199999999;j++){ }
system.out.println(name+"*****"+i+"--------"
+Thread.currentThread().getName());
}
}
}
main(){
Demo d1 = new Demo("臠割");
Demo d2 = new Demo("兒紙");
//d1.run();
//d2.run();
d1.start();
d2.start();
}
可以通過Thread的getName獲取線程的名稱 Thread—(0開始)
主線程的名稱是 main
創(chuàng)建線程的目的是為了開啟一條執(zhí)行路徑,去運行指定的代碼和其他代碼同時運行
而運行的指定代碼就是這個執(zhí)行路徑的任務(wù)
JV創(chuàng)建的主線程的任務(wù)都定義在主函數(shù)里
自定義的線程的任務(wù)在run方法里;
Thread類用于描述線程,線程是 需要任務(wù)的,所以Thread類也對任務(wù)的描述,這個任務(wù)就通過Thread類中的run方法實現(xiàn)。也就是說,run方法就是封裝自定義線程運行任務(wù)的函數(shù)。
run方法中定義的就是線程要運行的任務(wù)代碼
開啟線程是為了運行指定代碼,所以只有繼承Thread類,并復(fù)寫run方法,將要運行的代碼定義在run方法中即可。
run()和start()的區(qū)別:
1.start()可以啟動一個新的線程
2.start()不能重復(fù)調(diào)用run()可以
3.start()中的run()代碼可以不執(zhí)行完就繼續(xù)執(zhí)行下面的代碼,即進行了線程切換。直接調(diào)用run()方法必須等待其代碼全部執(zhí)行完才能繼續(xù)執(zhí)行下面的代碼
4.start()實現(xiàn)了多線程,run()沒有實現(xiàn)多線程
臨時阻塞狀態(tài) 具備執(zhí)行資格但不具備執(zhí)行權(quán) 正在等待執(zhí)行權(quán)
↑? ↑
↓? ? ? ? ? ? ? ? ? ? ? ↑
進程--->start()--->運行--->sleep(time)--->凍結(jié)//釋放執(zhí)行權(quán)的同時
| --->? wait()? --->↑? 釋放執(zhí)行資格
↓
stop()
|
↓
消亡
cpu執(zhí)行資格: 可以被cpu處理,在處理隊列中排隊
cpu的執(zhí)行權(quán): 正在被cpu處理
創(chuàng)建線程的第二種方法:
1.定義類實現(xiàn)Runnable接口
2.覆蓋接口種的run方法,將線程的任務(wù)代碼封裝到run方法中
3.通過Tread類創(chuàng)建對象,并將Runnable接口的子類對象作為Thread類的構(gòu)造函數(shù)的參數(shù)進行傳遞。(原因是線程任務(wù)都封裝在Runnable接口子類對象的run方法中,所以在線程對象創(chuàng)建時就得明確要運行的任務(wù)。)
4.調(diào)用線程對象的start方法開啟線程
class Demo2 implements Runnable //準備擴展Demo2類的功能,讓其中的內(nèi)容作為線程的任務(wù)執(zhí)行
//通過接口的形式完成
{
public void run()
{
show();
}
public void show(){
for(int i=1;i<10;i++)
{
for(long j= -199999999;j<199999999;j++){}
System.out.println(Thread.currentThread().getName());
}
}
}
main()
{
Demo2 d3 = new Demo2();
Thread t1 = new Thread(d3,"辦證");
Thread t2 = new Thread(d3,"學(xué)妹介紹Q");
t1.start();
t2.start();
}
Runnable接口:將線程的任務(wù)進行了對象的封裝
實現(xiàn)Runnable接口的好處:
1.將線程的任務(wù)從線程的子類中分離出來,進行了單獨的封裝
按照面向?qū)ο蟮乃枷雽⑷蝿?wù)的封裝成對象
2.避免了Java單繼承的局限性
故較為常用的是實現(xiàn)Runnable
線程安全問題產(chǎn)生的原因:
1.多個線程在操作共享的數(shù)據(jù)
2.操作共享數(shù)據(jù)的代碼有多條
當(dāng)一個線程在執(zhí)行操作共享數(shù)據(jù)的多條代碼過程中,其他線程參與了運算
就會導(dǎo)致線程安全問題的產(chǎn)生
解決思路:
就是將多條操作共享數(shù)據(jù)的線程代碼封裝起來,當(dāng)有線程在執(zhí)行這些代碼的時候,必須要當(dāng)成線程把這些代碼都執(zhí)行完畢后,其他線程才可以? ------->局部代碼塊
在Java中用同步代碼塊就可以解決這個問題
synchronized(對象)
{
局部代碼;
}
同步的好處:
解決了線程的安全問題
同步的弊端:
相對降低了效率,因為同步外的線程都會判斷同步鎖。
同步的前提:
同步中必須有多個線程嗎,并使用同一個鎖。
同步函數(shù)的鎖是this
同步函數(shù)和同步代碼塊的區(qū)別:
1.同步函數(shù)的鎖是固定的this
同步代碼塊的鎖是任意的對象
建議使用同步代碼塊
當(dāng)同步函數(shù)為static時,鎖為this.getClass()即該函數(shù)所屬字節(jié)碼文件對象,可用getClass()方法獲取,也可以用當(dāng)前
類名.class 表示。
死鎖:
class DeadLockTestDemo implements Runnable
{
private boolean flag;
DeadLockTestDemo(boolean flag)
{
this.flag = flag;
}
public void run()
{
if(flag)
{
while(true)
synchronized(MyLock.lockA)
{
System.out.println(Thread.currentThread().getName()+"--If--->LockA");
synchronized(MyLock.lockB)
{
System.out.println(Thread.currentThread().getName()+"--If--->LockB");
}
}
}
else
{
while(true)
synchronized(MyLock.lockB)
{
System.out.println(Thread.currentThread().getName()+"--Else--->LockB");
synchronized(MyLock.lockA)
{
System.out.println(Thread.currentThread().getName()+"--Else--->LockA");
}
}
}
}
}
class MyLock
{
public static final Object lockA = new Object();
public static final Object lockB = new Object();
}
public class DeakLockTest {
public static void main(String[] args) {
DeadLockTestDemo dlt1 = new DeadLockTestDemo(true);
DeadLockTestDemo dlt2 = new DeadLockTestDemo(false);
Thread t1 = new Thread(dlt1);
Thread t2 = new Thread(dlt2);
t1.start();
t2.start();
}
}
進程間的通信:
等待/喚醒機制
1.wait():讓cpu處于凍結(jié)狀態(tài),被wait的線程會被存儲到線程池中
2.notify(): 喚醒線程池中的一個線程(任意)
3.botifyAll():喚醒線程池中的所有線程
class Resource
{
String name;
int age;
boolean flag = false;
}
class Input implements Runnable
{
Resource r;
Input(Resource r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
synchronized(r)
{
if(r.flag)
try {
r.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(x==0)
{
r.name = "臠割";
r.age = 18;
}
else
{
r.name = "弟鴿";
r.age = 17;
}
r.flag = true;
r.notify();
}
x = (x+1)%2;
}
}
}
class Output implements Runnable
{
Resource r = new Resource();
Output(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
synchronized(r)
{
if(!r.flag)
try {
r.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(r.name+"--->"+r.age);
r.flag = false;
r.notify();
}
}
}
public class ResourceDemo {
public static void main(String[] args) {
Resource r = new Resource();
Input in = new Input(r);
Output out = new Output(r);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}
線程的wait();notify();notifuAll()定義在Oblect類中的原因是:
因為這些方法是監(jiān)視器的方法,監(jiān)視器其實就是鎖。
鎖可以是任意的對象,任意的對象調(diào)用的方式一定定義在Object類中
總結(jié)
以上是生活随笔為你收集整理的在java中5 % 3_Java基础5的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: git ssh拉取代码_win10下gi
- 下一篇: Java bitset转string_将