多線程停止的方法
- 設置一個標誌位。(無法處理線程阻塞時停止的問題)
- 調用Thread類提供的stop方法強行關閉線程。
這個方法已經不推薦使用了,因爲會產生不完整的數據。
class ThreadDemo extends Thread{
private boolean flag=true;
public void setflag(boolean flag){
this.flag=flag;
}
@Override
public void run() {
while(flag){
System.out.println("李明建是頭豬");
}
}
}
public class Solution {
public static void main(String[] args) throws InterruptedException {
Thread th1=new ThreadDemo();
th1.start();
Thread.sleep(1000);
//((ThreadDemo) th1).setflag(false) ;
th1.stop();
}
}
- 調用Thread類提供的interrupt();
a.若線程中沒有使用類似sleep/wait/join時,調用此線程對象的interrupt方法並不會中斷線程,只是簡單地將線程的狀態置爲interrupt而已,我們可以根據此狀態來進一步確定如何處理線程。
Thread類提供的public boolean isInterrupted()可以檢測當前線程狀態是否爲中斷狀態。
b.若線程中調用了阻塞線程的方法sleep()/wait()/join(),此時再調用線程的interrupt方法時會拋出異常,同時將線程狀態還原(isInterrupted=false)。
class ThreadDemo extends Thread{
@Override
public void run() {
while(!Thread.currentThread().isInterrupted()){
System.out.println("當前線程的狀態"+Thread.currentThread().isInterrupted());
}
if(Thread.currentThread().isInterrupted())
System.out.println("豬");
}
}
public class Solution {
public static void main(String[] args) throws InterruptedException {
Thread th1=new ThreadDemo();
th1.start();
Thread.sleep(1000);
th1.interrupt();
}
}
1.Thread.interrupted() 判斷當前線程的中斷標誌被設置,清除中斷標誌
2. Thread.currentThread().isInterrupted() 判斷指定線程的中斷標誌被設置,不清除中斷標誌
public class Solution2 {
/**
* interrupt 可以通過異常方式通知
*/
private static class MyThread1 extends Thread {
@Override
public void run() {
while (true) {
try {
Thread.sleep(10000000);
} catch (InterruptedException e) {
// 我收到了中斷通知
System.out.println(isInterrupted());
break;
}
}
System.out.println("退出");
}
}
private static class MyThread2 extends Thread {
@Override
public void run() {
while (!isInterrupted()) {
}
// 通過判斷中斷狀態退出,狀態不會被重置
System.out.println(isInterrupted());
System.out.println("退出");
}
}
private static class MyThread3 extends Thread {
@Override
public void run() {
while (!Thread.interrupted()) {
}
// 通過判斷中斷狀態退出,狀態被重置
System.out.println(Thread.interrupted());
System.out.println("退出");
}
}
public static void main(String[] args) {
// MyThread1 t1 = new MyThread1();
// t1.start();
// t1.interrupt();//false
// MyThread2 t2 = new MyThread2();
// t2.start();
// t2.interrupt();//true
MyThread3 t3 = new MyThread3();
t3.start();
t3.interrupt();//false
}
}
線程優先級
- 指的是優先級越高越有可能先執行
- getPriority() setPriority(int priority)
- 線程的繼承性:若在一個線程中創建了子線程,默認子線程與父線程的優先級相同。
守護線程
作爲陪伴線程,只要在JVM中存在有任何一個用戶線程沒有終止,守護線程就一直工作。
默認創建的線程都是用戶線程,包括主線程。通過setDaemon(true)將線程對象設置爲守護線程。
典型的守護線程:垃圾回收線程
線程同步(分工,同步,互斥)
1.互斥:多線程併發時,某一時刻只能有一個線程訪問共享資源。
2.鎖:一把鎖保護一個相應資源,不同鎖保護的不同的資源/對象
3.Java中鎖的實現:
使用synchroinzed關鍵字爲程序邏輯上鎖,有兩種用法:
a.同步代碼塊:
synchroinzed(鎖的對象|Object類及其子類){
//此處代碼塊在任意時刻只能有一個進程進入
}
class Demo extends Thread{
private int ticket;
public Demo(int ticket) {
this.ticket=ticket;
}
@Override
public void run() {
//條件處只能在某一時刻只有一個線程,需要爲程序段上鎖
for(int i=0;i<100;i++){
//需要在判斷出上鎖
synchronized (this){
//在任意時刻只有一個線程能進入條件判斷
if(ticket>0) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() +"還剩下" + ticket-- + "票");
}
}
}
}
}
public class Solution3 {
public static void main(String[] args) {
Demo a=new Demo(100);
Thread th1=new Thread(a,"A");
Thread th2=new Thread(a,"B");
Thread th3=new Thread(a,"C");
th1.start();
th2.start();
th3.start();
}
}
b. 同步方法:直接在方法聲明上使用 synchronized,此時表示同步方法在任意時刻只能有一個線程進入。
//默認鎖的是this
public synchronized void sell(){
}
class Demo extends Thread{
private int ticket;
public Demo(int ticket) {
this.ticket=ticket;
}
@Override
public void run() {
//條件處只能在某一時刻只有一個線程,需要爲程序段上鎖
for(int i=0;i<100;i++){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
sell();
}
}
//在任意時刻只能有一個線程進入此方法
public synchronized void sell() {
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "還剩下" + ticket-- + "票");
}
}
}
public class Solution3 {
public static void main(String[] args) {
Demo a=new Demo(100);
Thread th1=new Thread(a,"A");
Thread th2=new Thread(a,"B");
Thread th3=new Thread(a,"C");
th1.start();
th2.start();
th3.start();
}
}
若synchronized修飾的是靜態的方法或synchronized(類名稱.class)synchronized鎖的都是當前類的反射對象(全局唯一)。