Java實例-線程

1、Java 實例 – 查看線程是否存活:通過繼承 Thread 類并使用 isAlive() 方法來檢測一個線程是否存活。

public class Thread_Aliveextends Thread{

public void run() {

for (int i =0; i <2; i++) {

printMsg();

}

}

public void printMsg() {

Thread t = Thread.currentThread();

String name = t.getName();

System.out.println("name=" + name);

}

public static void main(String[] args) {

Thread_Alive tt =new Thread_Alive();

tt.setName("Thread");

System.out.println("before start(), tt.isAlive()=" + tt.isAlive());

tt.start();

System.out.println("just after start(), tt.isAlive()=" + tt.isAlive());

for (int i =0; i <10; i++) {

tt.printMsg();

}

System.out.println("The end of main(), tt.isAlive()=" + tt.isAlive());

}

}

執(zhí)行結(jié)果:

2、Java 實例 – 獲取當前線程名稱:通過繼承 Thread 類并使用 getName() 方法來獲取當前線程名稱。

public class Thread_GetName extends Thread{

public void run() {

for (int i =0; i <2; i++) {

printMsg();

}

}

public void printMsg() {

Thread t = Thread.currentThread();

String name = t.getName();

System.out.println("name=" + name);

}

public static void main(String[] args) {

Thread_GetName tt =new Thread_GetName();

tt.start();

for (int i =0; i <10; i++) {

tt.printMsg();

}

}

}

執(zhí)行結(jié)果:

3、Java 實例 – 狀態(tài)監(jiān)測:通過繼承 Thread 類并使用 currentThread.getName() 方法來監(jiān)測線程的狀態(tài)。

public class Thread_Testextends Thread{

boolean waiting=true;

boolean ready=false;

Thread_Test() {

}

public void run() {

String thrdName = Thread.currentThread().getName();

System.out.println(thrdName +" starting.");

while(waiting)

System.out.println("waiting:"+waiting);

System.out.println("waiting...");

startWait();

try {

Thread.sleep(10);

}

catch(Exception exc) {

System.out.println(thrdName +" interrupted.");

}

System.out.println(thrdName +" terminating.");

}

synchronized void startWait() {

try {

while(!ready) wait();

}

catch(InterruptedException exc) {

System.out.println("wait() interrupted");

}

}

synchronized void notice() {

ready =true;

notify();

}

}

······································································

public class Test_Main {

public static void main(String args[])throws Exception{

Thread_Test thrd =new Thread_Test();

thrd.setName("MyThread #1");

showThreadStatus(thrd);

thrd.start();

Thread.sleep(10);

showThreadStatus(thrd);

thrd.waiting =false;

Thread.sleep(10);

showThreadStatus(thrd);

thrd.notice();

Thread.sleep(10);

showThreadStatus(thrd);

while(thrd.isAlive())

System.out.println("alive");

showThreadStatus(thrd);

}

static void showThreadStatus(Thread thrd) {

System.out.println(thrd.getName() +"Alive:=" + thrd.isAlive() +" State:=" + thrd.getState());

}

}

執(zhí)行結(jié)果:


4、Java 實例 – 線程優(yōu)先級設置:通過setPriority() 方法來設置線程的優(yōu)先級。

public class Thread_Prioritiesextends Thread{

private int countDown =3;

private volatile double d =0;

public Thread_Priorities(int priority) {

setPriority(priority);

start();

}

public String toString() {

return super.toString() +": " +countDown;

}

public void run() {

while(true) {

for(int i =1; i <100000; i++)

d =d + (Math.PI + Math.E) / (double)i;

System.out.println(this);

if(--countDown ==0)return;

}

}

public static void main(String[] args) {

new Thread_Priorities(Thread.MAX_PRIORITY);

for(int i =0; i <5; i++)

new Thread_Priorities(Thread.MIN_PRIORITY);

}

}

執(zhí)行結(jié)果:

5、Java 實例 – 死鎖及解決方法:

????死鎖:多個線程同時被阻塞,它們中的一個或者全部都在等待某個資源被釋放。由于線程被無限期地阻塞,因此程序不可能正常終止。

java 死鎖產(chǎn)生的四個必要條件:

1、互斥使用,即當資源被一個線程使用(占有)時,別的線程不能使用

2、不可搶占,資源請求者不能強制從資源占有者手中奪取資源,資源只能由資源占有者主動釋放。

3、請求和保持,即當資源請求者在請求其他的資源的同時保持對原有資源的占有。

4、循環(huán)等待,即存在一個等待隊列:P1占有P2的資源,P2占有P3的資源,P3占有P1的資源。這樣就形成了一個等待環(huán)路。

解決死鎖問題的方法是:一種是用synchronized,一種是用Lock顯式鎖實現(xiàn)。

死鎖:

public class Thread_LockAimplements Runnable{

public void run() {

try {

System.out.println(new Date().toString() +" LockA 開始執(zhí)行");

while(true){

synchronized (Lock_Main.obj1) {

System.out.println(new Date().toString() +" LockA 鎖住 obj1");

Thread.sleep(3000);// 此處等待是給B能鎖住機會

? ? ? ? ? ? ? ? ? ? synchronized (Lock_Main.obj2) {

System.out.println(new Date().toString() +" LockA 鎖住 obj2");

Thread.sleep(60 *1000);// 為測試,占用了就不放

? ? ? ? ? ? ? ? ? ? }

}

}

}catch (Exception e) {

e.printStackTrace();

}

}

}

·····················································································

public class Thread_LockBimplements Runnable{

public void run() {

try {

System.out.println(new Date().toString() +" LockB 開始執(zhí)行");

while(true){

synchronized (Lock_Main.obj2) {

System.out.println(new Date().toString() +" LockB 鎖住 obj2");

Thread.sleep(3000);// 此處等待是給A能鎖住機會

? ? ? ? ? ? ? ? ? ? synchronized (Lock_Main.obj1) {

System.out.println(new Date().toString() +" LockB 鎖住 obj1");

Thread.sleep(60 *1000);// 為測試,占用了就不放

? ? ? ? ? ? ? ? ? ? }

}

}

}catch (Exception e) {

e.printStackTrace();

}

}

}

·············································································

public class Lock_Main {

public static Stringobj1 ="obj1";

public static Stringobj2 ="obj2";

public static void main(String[] args) {

Thread_LockA la =new Thread_LockA();

new Thread(la).start();

Thread_LockB lb =new Thread_LockB();

new Thread(lb).start();

}

}

執(zhí)行結(jié)果:

解決死鎖:

public class Thread_LockAaimplements Runnable{

public void run() {

try {

System.out.println(new Date().toString() +" LockA 開始執(zhí)行");

while (true) {

if (UnLock_Main.a1.tryAcquire(1, TimeUnit.SECONDS)) {

System.out.println(new Date().toString() +" LockA 鎖住 obj1");

if (UnLock_Main.a2.tryAcquire(1, TimeUnit.SECONDS)) {

System.out.println(new Date().toString() +" LockA 鎖住 obj2");

Thread.sleep(60 *1000);// do something

? ? ? ? ? ? ? ? ? ? }else{

System.out.println(new Date().toString() +"LockA 鎖 obj2 失敗");

}

}else{

System.out.println(new Date().toString() +"LockA 鎖 obj1 失敗");

}

UnLock_Main.a1.release();// 釋放

? ? ? ? ? ? ? ? UnLock_Main.a2.release();

Thread.sleep(1000);// 馬上進行嘗試,現(xiàn)實情況下do something是不確定的

? ? ? ? ? ? }

}catch (Exception e) {

e.printStackTrace();

}

}

}

·········································································

public class Thread_LockBbimplements Runnable{

public void run() {

try {

System.out.println(new Date().toString() +" LockB 開始執(zhí)行");

while (true) {

if (UnLock_Main.a2.tryAcquire(1, TimeUnit.SECONDS)) {

System.out.println(new Date().toString() +" LockB 鎖住 obj2");

if (UnLock_Main.a1.tryAcquire(1, TimeUnit.SECONDS)) {

System.out.println(new Date().toString() +" LockB 鎖住 obj1");

Thread.sleep(60 *1000);// do something

? ? ? ? ? ? ? ? ? ? }else{

System.out.println(new Date().toString() +"LockB 鎖 obj1 失敗");

}

}else{

System.out.println(new Date().toString() +"LockB 鎖 obj2 失敗");

}

UnLock_Main.a1.release();// 釋放

? ? ? ? ? ? ? ? UnLock_Main.a2.release();

Thread.sleep(10 *1000);// 這里只是為了演示,所以tryAcquire只用1秒,而且B要給A讓出能執(zhí)行的時間,否則兩個永遠是死鎖

? ? ? ? ? ? }

}catch (Exception e) {

e.printStackTrace();

}

}

}

········································································

public class UnLock_Main {

public static Stringobj1 ="obj1";

public static final Semaphorea1 =new Semaphore(1);

public static Stringobj2 ="obj2";

public static final Semaphorea2 =new Semaphore(1);

public static void main(String[] args) {

Thread_LockAa la =new Thread_LockAa();

new Thread(la).start();

Thread_LockBb lb =new Thread_LockBb();

new Thread(lb).start();

}

}

執(zhí)行結(jié)果:

6、Java 實例 – 獲取線程id:使用 getThreadId() 方法獲取線程id。

public class ThreadIDextends ThreadLocal {

private int nextID;

public ThreadID() {

nextID =10001;

}

private synchronized Integer getNewID() {

Integer id =new Integer(nextID);

nextID++;

return id;

}

protected Object initialValue() {

print("in initialValue()");

return getNewID();

}

public int getThreadID() {

Integer id = (Integer) get();

return id.intValue();

}

private static void print(String msg) {

String name = Thread.currentThread().getName();

System.out.println(name +": " + msg);

}

}

····················································································

public class ID_Main extends Objectimplements Runnable{

private ThreadIDvar;

public ID_Main(ThreadID v) {

this.var = v;

}

public void run() {

try {

print("var getThreadID =" +var.getThreadID());

Thread.sleep(2000);

print("var getThreadID =" +var.getThreadID());

}catch (InterruptedException x) {

}

}

private static void print(String msg) {

String name = Thread.currentThread().getName();

System.out.println(name +": " + msg);

}

public static void main(String[] args) {

ThreadID tid =new ThreadID();

ID_Main shared =new ID_Main(tid);

try {

Thread threadA =new Thread(shared,"threadA");

threadA.start();

Thread.sleep(500);

Thread threadB =new Thread(shared,"threadB");

threadB.start();

Thread.sleep(500);

Thread threadC =new Thread(shared,"threadC");

threadC.start();

}catch (InterruptedException x) {

}

}

}

執(zhí)行結(jié)果:

7、Java 實例 – 線程掛起:

public class Thread_Sleepingextends Thread{

private int countDown =3;

private static int threadCount =0;

public Thread_Sleeping() {

super("" + ++threadCount);

start();

}

public String toString() {

return "#" + getName() +": " +countDown;

}

public void run() {

while (true) {

System.out.println(this);

if (--countDown ==0)

return;

try {

sleep(100);

}

catch (InterruptedException e) {

throw new RuntimeException(e);

}

}

}

public static void main(String[] args)

throws InterruptedException {

for (int i =0; i <3; i++)

new Thread_Sleeping().join();

System.out.println("線程已被掛起");

}

}

執(zhí)行結(jié)果:

8、Java 實例 – 終止線程:Java中原來在Thread中提供了stop()方法來終止線程,但這個方法是不安全的,所以一般不建議使用。該實例使用interrupt方法來終端線程,可分為兩種情況:

(1)線程處于阻塞狀態(tài),如使用了sleep方法。

(2)使用while(!isInterrupted()){……}來判斷線程是否被中斷。

在第一種情況下使用interrupt方法,sleep方法將拋出一個InterruptedException例外,而在第二種情況下線程將直接退出。

public class Thread_Interruptextends Thread

{

public void run()

{

try

? ? ? ? {

sleep(50000);// 延遲50秒

? ? ? ? }

catch (InterruptedException e)

{

System.out.println(e.getMessage());

}

}

public static void main(String[] args)throws Exception

{

Thread thread =new Thread_Interrupt();

thread.start();

System.out.println("在50秒之內(nèi)按任意鍵中斷線程!");

System.in.read();

thread.interrupt();

thread.join();

System.out.println("線程已經(jīng)退出!");

}

}

執(zhí)行結(jié)果:

9、Java 實例 – 生產(chǎn)者/消費者問題:生產(chǎn)者和消費者問題是線程模型中的經(jīng)典問題:生產(chǎn)者和消費者在同一時間段內(nèi)共用同一個存儲空間,如下圖所示,生產(chǎn)者向空間里存放數(shù)據(jù),而消費者取用數(shù)據(jù),如果不加以協(xié)調(diào)可能會出現(xiàn)以下情況:

存儲空間已滿,而生產(chǎn)者占用著它,消費者等著生產(chǎn)者讓出空間從而去除產(chǎn)品,生產(chǎn)者等著消費者消費產(chǎn)品,從而向空間中添加產(chǎn)品?;ハ嗟却瑥亩l(fā)生死鎖。


class Consumer extends Thread {

private CubbyHolecubbyhole;

private int number;

public Consumer(CubbyHole c,int number) {

cubbyhole = c;

this.number = number;

}

public void run() {

int value =0;

for (int i =0; i <3; i++) {

value =cubbyhole.get();

System.out.println("消費者 #" +this.number+" got: " + value);

}

}

}

·······················································································

class Producer extends Thread {

private CubbyHolecubbyhole;

private int number;

public Producer(CubbyHole c,int number) {

cubbyhole = c;

this.number = number;

}

public void run() {

for (int i =0; i <3; i++) {

cubbyhole.put(i);

System.out.println("生產(chǎn)者 #" +this.number +" put: " + i);

try {

sleep((int)(Math.random() *100));

}catch (InterruptedException e) { }

}

}

}

·······················································································

public class CubbyHole {

private int contents;

private boolean available =false;

public synchronized int get() {

while (available ==false) {

try {

wait();

}

catch (InterruptedException e) {

}

}

available =false;

notifyAll();

return contents;

}

public synchronized void put(int value) {

while (available ==true) {

try {

wait();

}

catch (InterruptedException e) {

}

}

contents = value;

available =true;

notifyAll();

}

}

·······················································································

public class P_C_Main {

public static void main(String[] args) {

CubbyHole c =new CubbyHole();

Producer p1 =new Producer(c,1);

Consumer c1 =new Consumer(c,1);

p1.start();

c1.start();

}

}

執(zhí)行結(jié)果:

10、Java 實例 – 獲取線程狀態(tài):

????Java中的線程的生命周期大體可分為5種狀態(tài)。

1. 新建狀態(tài)(New):新創(chuàng)建了一個線程對象。

2. 就緒狀態(tài)(Runnable):線程對象創(chuàng)建后,其他線程調(diào)用了該對象的start()方法。該狀態(tài)的線程位于可運行線程池中,變得可運行,等待獲取CPU的使用權。

3. 運行狀態(tài)(Running):就緒狀態(tài)的線程獲取了CPU,執(zhí)行程序代碼。

4. 阻塞狀態(tài)(Blocked):阻塞狀態(tài)是線程因為某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態(tài),才有機會轉(zhuǎn)到運行狀態(tài)。阻塞的情況分三種:

(一)、等待阻塞:運行的線程執(zhí)行wait()方法,JVM會把該線程放入等待池中。

(二)、同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程占用,則JVM會把該線程放入鎖池中。

(三)、其他阻塞:運行的線程執(zhí)行sleep()或join()方法,或者發(fā)出了I/O請求時,JVM會把該線程置為阻塞狀態(tài)。當sleep()狀態(tài)超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉(zhuǎn)入就緒狀態(tài)。

5. 死亡狀態(tài)(Dead):線程執(zhí)行完了或者因異常退出了run()方法,該線程結(jié)束生命周期。

執(zhí)行結(jié)果:


11、Java 實例 – 獲取所有線程:使用 getName() 方法獲取所有正在運行的線程。

public class Thread_Getextends Thread{

public static void main(String[] args) {

Thread_Get t1 =new Thread_Get();

t1.setName("thread1");

t1.start();

ThreadGroup currentGroup =

Thread.currentThread().getThreadGroup();

int noThreads = currentGroup.activeCount();

Thread[] lstThreads =new Thread[noThreads];

currentGroup.enumerate(lstThreads);

for (int i =0; i < noThreads; i++)

System.out.println("線程號:" + i +" = " + lstThreads[i].getName());

}

}

執(zhí)行結(jié)果:

12、Java 實例 – 查看線程優(yōu)先級:使用 getThreadId() 方法獲取線程id。

public class Thread_LookPrioities {

private static Runnable makeRunnable() {

Runnable r =new Runnable() {

public void run() {

for (int i =0; i <5; i++) {

Thread t = Thread.currentThread();

System.out.println("in run() - priority="

? ? ? ? ? ? ? ? ? ? ? ? ? ? + t.getPriority()+", name=" + t.getName());

try {

Thread.sleep(2000);

}

catch (InterruptedException x) {

}

}

}

};

return r;

}

public static void main(String[] args) {

System.out.println("in main() - Thread.currentThread().getPriority()=" + Thread.currentThread().getPriority());

System.out.println("in main() - Thread.currentThread().getName()="+ Thread.currentThread().getName());

Thread threadA =new Thread(makeRunnable(),"threadA");

threadA.start();

try {

Thread.sleep(3000);

}

catch (InterruptedException x) {

}

System.out.println("in main() - threadA.getPriority()="+ threadA.getPriority());

}

}

執(zhí)行結(jié)果:

13、Java 實例 – 中斷線程:使用interrupt()方法來中斷線程并使用 isInterrupted() 方法來判斷線程是否已中斷。

public class Thread_InterruptStatusextends Object

implements Runnable{

public void run() {

try {

System.out.println("in run() - 將運行 work2() 方法");

work2();

System.out.println("in run() - 從 work2() 方法回來");

}

catch (InterruptedException x) {

System.out.println("in run() - 中斷 work2() 方法");

return;

}

System.out.println("in run() - 休眠后執(zhí)行");

System.out.println("in run() - 正常離開");

}

public void work2()throws InterruptedException {

while (true) {

if (Thread.currentThread().isInterrupted()) {

System.out.println("C isInterrupted()=" + Thread.currentThread().isInterrupted());

Thread.sleep(2000);

System.out.println("D isInterrupted()=" + Thread.currentThread().isInterrupted());

}

}

}

public void work()throws InterruptedException {

while (true) {

for (int i =0; i <100000; i++) {

int j = i *2;

}

System.out.println("A isInterrupted()=" + Thread.currentThread().isInterrupted());

if (Thread.interrupted()) {

System.out.println("B isInterrupted()=" + Thread.currentThread().isInterrupted());

throw new InterruptedException();

}

}

}

public static void main(String[] args) {

Thread_InterruptStatus si =new Thread_InterruptStatus();

Thread t =new Thread(si);

t.start();

try {

Thread.sleep(2000);

}

catch (InterruptedException x) {

}

System.out.println("in main() - 中斷其他線程");

t.interrupt();

System.out.println("in main() - 離開");

}

}

執(zhí)行結(jié)果:

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • Java多線程學習 [-] 一擴展javalangThread類 二實現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 3,105評論 1 18
  • 本文主要講了java中多線程的使用方法、線程同步、線程數(shù)據(jù)傳遞、線程狀態(tài)及相應的一些線程函數(shù)用法、概述等。 首先講...
    李欣陽閱讀 2,591評論 1 15
  • JUC 原創(chuàng)者:文思,感謝尚硅谷,資料來源于尚硅谷 目錄: 1、volatile關鍵字與內(nèi)存可見性 2、原子變量與...
    文思li閱讀 2,520評論 0 1
  • 多線程概述 通過子類繼承開啟多線程public class Demo { public static voi...
    JerichoPH閱讀 395評論 0 2
  • 小編費力收集:給你想要的面試集合 1.C++或Java中的異常處理機制的簡單原理和應用。 當JAVA程序違反了JA...
    八爺君閱讀 5,172評論 1 114

友情鏈接更多精彩內(nèi)容