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é)果:
