java支持多线程吗_Java多线程之一
進程與線程
進程
進程是進程實體的運行過程,是系統進行資源分配和調度的一個獨立單位,比如我們windows電腦上運行的一個程序就是一個進程。在傳統進程中進程是資源分配和調度的一個基本單位,在后來引入線程概念后,進程就變成了資源分配的基本單位但不是調度的基本單位。
為什么要有線程
在說線程前,總結下進程的特點:
進程是一個可擁有資源的獨立單位;
進程是一個可獨立調度和分派的基本單位。
這樣來看的話好像是沒什么問題,但是在多任務環境中,不可能說讓所有任務排隊,前面的處理完了才處理后面的任務。如果要讓用戶感覺到任務都是一起執行的,那么就必須在進程之間頻繁切換。問題在于如果要進行進程的切換需要做很多的工作,必須要保存好當前CPU的上下文,好讓CPU下次被分配到當前進程時可以繼續往前執行,然后還需要設置新的進程的CPU上下文,在這個過程中會花費很多時間。由于這個原因就限制了系統中進程數目不能多。
為了解決這個限制,后來提出將進程的兩個屬性分開,由操作系統分開處理,即對于作為調度和分派的基本單位,但不同時作為擁有資源的單位;而對于擁有資源的基本單位,又不對其進行頻繁的切換。正是在這種思想的指導下,形成了線程的概念。
線程
在多線程操作系統中中,通常是在一個進程中包括多個線程,每個線程都是獨立調度和分派的基本單位。資源由進程來擁有,線程不擁有資源。同一個進程之間的線程切換不會導致進程的切換,只有不同進程間的線程切換才會導致進程切換。而且線程的切換則僅需保存和設置少量寄存器內容,不會同進程切換需求創建和銷毀進程控制塊等,所以非常迅速,所以其十分適合高并發環境。
線程的狀態(Java)
public enum State {
NEW,//新建 線程被創建,但是沒有調用start方法
RUNNABLE,//可運行 表示當前線程可以運行,但實際是否運行有cpu決定
BLOCKED,//阻塞 其他線程獲得鎖,當前線程被阻塞在獲得鎖處
WAITING,//等待 等待其他條件成熟進入可運行狀態
TIMED_WAITING,//計時等待 在一個指定時間內等待,超時后放棄
TERMINATED;//終止 線程執行完畢
}
線程的創建方式
Thread
繼承Thread類:
class TestThread extends Thread{
@Override
public void run() {
super.run();
//do working
}
}
Runnable
實現Runnable接口:
static class TestRunnale implements Runnable{
@Override
public void run() {
//do working
}
}
public static void main(String[] args) {
TestRunnale runnale = new TestRunnale();
Thread thread = new Thread(runnale);
thread.start();
}
線程的中斷
不安全的中斷
在Thread的api中提供了一些終止線程的方法,比如stop(),suspend(),resume(),但是這些方法目前在JDK中已經被標記位過時,因為這些方法具有死鎖傾向,已經被明確表示不支持使用。
中斷線程API
interrupt() 中斷線程,本質是將線程的中斷標志位設為true,其他線程向需要中斷的線程打個招呼。是否真正進行中斷由線程自己決定。
isInterrupted() 線程檢查自己的中斷標志位
靜態方法Thread.interrupted() 將中斷標志位復位為false
中斷標志位
自定義一個Boolean類型的中斷標志位,提供一個中斷方法,線程一直循環檢測該標志位,標志位被設置為退出狀態是終止線程。
public class FlagCancel {
static class Flag extends Thread{
//中斷標志
public static boolean flag = false;
@Override
public void run() {
int i = 0;
while(!flag){
System.out.println(i++);
if(i>=3){
try {
Thread.sleep(200);
//interrupt();
if(i == 10)
cancel();//修改中斷狀態,退出線程
System.out.println("thread:" + isInterrupted());
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("cancel...");
}
}
}
public static void cancel(){
flag = true;
}
}
public static void main(String[] args) {
Flag test = new Flag();
test.start();
test.setPriority(10);//這里的設置優先級其實沒什么用。cpu不會理你的。。。
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main:" + test.isInterrupted());//這里屬于主線程(main)
}
}
正常來說上面的形式沒有什么問題,我們寫代碼的時候,提供一個修改中斷為狀態的方法,并根據我們自己的業務邏輯來定義什么時候中斷,但是如果我們手動設置中斷就有問題了,將上面代碼中注釋的interrupt();打開。interrupt()方法是用來中斷線程的,但是在上面的邏輯中即使調用了該方法也不會立即中斷,而必須要等待中斷為被修改后才能退出。
安全的中斷
上面介紹了中斷相關的api和使用中斷標志位來中斷線程,但是中斷標記位無法捕獲異常情況。但是isInterrupted()方法會一直檢查線程的中斷狀態,所以我們可以用這個方法來實現安全的中斷。
public class SafeInterrupt extends Thread {
private boolean flag = false;
@Override
public void run() {
int i = 0;
System.out.println(Thread.currentThread().getName() + ":" +Thread.currentThread().isInterrupted());
while (!flag && !Thread.currentThread().isInterrupted()) {
System.out.println(i++);
try {
synchronized (this) {
if (i > 3) {
//Thread.sleep(1000 * 60 * 60 * 24);
wait();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 這里必須將需要中斷的線程作為參數傳過來
* 用以進行中斷
* @param t(Thread)
*/
public void cancel(Thread t) {
System.out.println("ready stop currentThread...");
flag = true;
//將需要中斷的線程的中斷標志位設置為true
t.interrupt();
System.out.println(t.getName() + ":" + t.isInterrupted());
}
public static void main(String[] args) throws InterruptedException {
SafeInterrupt safeInterrupt = new SafeInterrupt();
safeInterrupt.start();
Thread.sleep(100);
safeInterrupt.cancel(safeInterrupt);
}
}
不可中斷的情況
好了,到現在我們已經可以安全的處理線程的中斷了,但是還沒完,因為不是所有的線程都是會響應中斷的。比如IO的read()/write() 等就不會響應中斷。而如果我們想不讓其繼續阻塞的話就需要我們手動的關閉底層的套接字。
public class CloseSocket extends Thread {
private Socket socket;
private InputStream in;
public CloseSocket(Socket socket, InputStream in) {
this.socket = socket;
this.in = in;
}
//重寫中斷方法 在中斷線程時中斷套接字
@Override
public void interrupt() {
try {
//關閉底層套接字
socket.close();
} catch (IOException e) {
e.printStackTrace();
}finally {
//中斷線程
super.interrupt();
}
}
}
還有想死鎖之類的不響應中斷的情況用代碼已經基本解決不了了,只能檢查代碼修改重啟服務器啦。
總結
以上是生活随笔為你收集整理的java支持多线程吗_Java多线程之一的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android edittext 正则限
- 下一篇: mysql封装执行_解决Mysql封装类