進程與線程的理解:
進程是指:一個內存中運行的應用程序,每個進程都有自己獨立的一塊內存空間,一個進程中可以啓動多個線程。比如在Windows系統中,一個運行的exe就是一個進程。
線程是指:進程中的一個執行流程,一個進程中可以運行多個線程。比如java.exe進程中可以運行很多線程。線程總是屬於某個進程,進程中的多個線程共享進程的內存。
線程的狀態
1、線程共有下面5種狀態:
· 新建狀態(New):新創建了一個線程對象,當你用new創建一個線程時,該線程尚未運行。
· 就緒狀態(Runnable):線程對象創建後,其他線程調用了該對象的start()方法。該狀態的線程位於可運行線程池中,變得可運行,等待獲取CPU的使用權。
· 運行狀態(Running):就緒狀態的線程獲取了CPU,執行程序代碼。
· 阻塞狀態(Blocked):阻塞狀態是線程因爲某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,纔有機會轉到運行狀態。阻塞的情況分三種:
a. 等待阻塞:運行的線程執行wait()方法,JVM會把該線程放入等待池中。
b. 同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則JVM把該線程放入鎖。
c. 其他阻塞:運行的線程執行sleep()或join()方法,或者發出了I/O請求時,JVM會把該線程置爲阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。
· 死亡狀態(Dead):
a. 由於run方法的正常退出而自然死亡;
b. 沒有捕獲到的異常事件終止了run方法的執行,從而導致線程突然死亡
JAVA多線程實現方式
JAVA多線程實現方式主要有以下三種:
1、繼承Thread類
2、實現Runnable接口
比較:繼承Thread和實現Runnable接口都是創建線程的方法,唯一的區別在與java只允許單一繼承,但可以實現多個接口。
3、使用ExecutorService、Callable、Future實現有返回結果的多線程。
1、繼承Thread類實現多線程
繼承Thread類的方法儘管被我列爲一種多線程實現方式,但Thread本質上也是實現了Runnable接口的一個實例,它代表一個線程的實例,並且,啓動線程的唯一方法就是通過Thread類的start()實例方法。start()方法是一個native方法,它將啓動一個新線程,並執行run()方法。這種方式實現多線程很簡單,通過自己的類直接extend Thread,並複寫run()方法,就可以啓動新線程並執行自己定義的run()方法。
例如:
· package thread;
·
· public class MyThread extends Thread {
· public void run() {
· System.out.println("run()方法正在執行");
· }
· }
啓動線程方式如下:
· MyThread myThread1 = new MyThread();
· MyThread myThread2 = new MyThread();
· myThread1.start();
· myThread2.start();
2、實現Runnable接口方式實現多線程
如果自己的類已經extends另一個類,就無法直接extends Thread,此時,必須實現一個Runnable接口。
方法如下:
· package thread;
· class OtherClass{
· public void print(String str){
· System.out.println(str);
· }
· }
·
· public class MyThread extends OtherClass implements Runnable {
· public void run() {
· System.out.println("run()正在執行");
· }
· }
爲了啓動MyThread,需要首先實例化一個Thread,並傳入自己的MyThread實例。
具體方法如下:
· MyThread myThread = new MyThread();
· Thread thread = new Thread(myThread);
· thread.start();
事實上,當傳入一個Runnable target參數給Thread後,Thread的run()方法就會調用target.run(),參考JDK源代碼:
· public void run() {
· if (target != null) {
· target.run();
· }
· }
學會了線程的創建方式,下面我們在舉幾個線程狀態轉換的例子
Java線程函數
1創建線程,線程處於就緒新建狀態,但還沒有一個真正的線程
Thread(Runnable target)
Thread(Runnable target, String name)
Thread(ThreadGroup group, Runnable target)
Thread(ThreadGroup group, Runnable target, String name)
Thread(ThreadGroup group, Runnable target, String name, long stackSize)
2 啓動線程,線程處於運行狀態
start():啓動線程
3暫停線程,線程處於阻塞狀態
yield():暫定線程的執行,允許其它線程競爭CPU,常用於具有同等優先級的線程之間的競爭,適用於不支持時間分片的操作系統之間的線程處理。
sleep(long millis):線程休眠,暫停執行,但是不交出臨界區的鎖。
stop():kill一個線程,但是通常通過線程內的循環條件來結束一個線程。
public void interrupt() 中斷線程
4設置線程的優先級,低優先級的線程處於就緒狀態,還未獲得CPU使用的機會
setPriority(int weight):設置線程的優先級(1->10),值越高,優先級越高,一般是5,且子線程與母線程具有同等的優先級和線程屬性(是否爲前後臺線程)。
setDaemon(true):在start()方法前執行,將該線程設置爲後臺線程,後臺線程在所有前臺線程執行完後亦自行終止。
5檢測線程的狀態
isAlive():判斷此線程是否處於處於活動狀態,如果在start()後,線程終止前,該方法返回true。
線程狀態的轉換實例
· package thread;
·
· public class ThreadStateDemo extends Thread {
·
· Thread thread;
·
· public ThreadStateDemo() {
· thread = new Thread(this);
· System.out.println("創建一個線程:thread");
· thread.start();
· }
·
· public void run() {
· try {
· System.out.println("線程thread正在運行!");
· System.out.println("線程thread睡眠3秒中...!");
· Thread.sleep(3000); //靜態方法,使當前正在執行的線程睡眠3秒
· System.out.println("線程thread在睡眠後重新運行!");
· }catch(InterruptedException e) {
· System.out.println("線程被中斷");
· }
· }
·
· public static void main(String[] args) {
· new ThreadStateDemo();
· System.out.println("主線程main結束!");
· }
· }
線程的同步
同步就是協同步調,按預定的先後次序進行運行。
1線程相互影響
public class synchronize1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//共享代碼段
Shared shared=new Shared();
//創建進程
CustomThread thread1=new CustomThread(shared,"one");
CustomThread thread2=new CustomThread(shared,"two");
CustomThread thread3=new CustomThread(shared,"three");
CustomThread thread4=new CustomThread(shared,"four");
try{
//jion()方法使得當前線程暫停執行,等待調用該方法的線程結束後再繼續執行本線程
thread1.join();
thread2.join();
thread3.join();
thread4.join();
}catch(InterruptedException e){}
}
}
class CustomThread extends Thread{
Shared shared;
public CustomThread(Shared shared,String string){
super(string);
this.shared=shared;
start();
}
public void run(){
shared.doWork(Thread.currentThread().getName());
}
}
class CustomThread2 implements Runnable{
Shared shared;
Thread thread=new Thread();
public CustomThread2(Shared shared,String string){
this.shared=shared;
thread.start();
}
public void join() throws InterruptedException {
// TODO Auto-generated method stub
thread.join();
}
public void run(){
shared.doWork(Thread.currentThread().getName());
}
}
//共享代碼段
class Shared{
void doWork(String string){
System.out.println("Strating "+string);
try{
Thread.sleep((long)(Math.random()*500));
}catch(InterruptedException e){}
System.out.println("Ending"+string);
}
}
2使用 synchronized關鍵字來聲明要禁止訪問的對象
public class synchronize2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//共享代碼段
Shared shared=new Shared();
//創建進程
CustomThread thread1=new CustomThread(shared,"one");
CustomThread thread2=new CustomThread(shared,"two");
CustomThread thread3=new CustomThread(shared,"three");
CustomThread thread4=new CustomThread(shared,"four");
try{
//jion()方法使得當前線程暫停執行,等待調用該方法的線程結束後再繼續執行本線程
thread1.join();
thread2.join();
thread3.join();
thread4.join();
}catch(InterruptedException e){}
}
}
class CustomThread extends Thread{
Shared shared;
public CustomThread(Shared shared,String string){
super(string);
this.shared=shared;
start();
}
public void run(){
//實現同步
synchronized(shared)
{
shared.doWork(Thread.currentThread().getName());
}
}
}
class CustomThread2 implements Runnable{
Shared shared;
Thread thread=new Thread();
public CustomThread2(Shared shared,String string){
this.shared=shared;
thread.start();
}
public void join() throws InterruptedException {
// TODO Auto-generated method stub
thread.join();
}
public void run(){
shared.doWork(Thread.currentThread().getName());
}
}
//共享代碼段
class Shared{
void doWork(String string){
System.out.println("Strating "+string);
try{
Thread.sleep((long)(Math.random()*500));
}catch(InterruptedException e){}
System.out.println("Ending"+string);
}
}
3使用 synchronized關鍵字來聲明要禁止訪問的方法,阻塞其他線程的通路,使某一時刻只有一個線程可以進入方法
public class synchronize3 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//共享代碼段
Shared shared=new Shared();
//創建進程
CustomThread thread1=new CustomThread(shared,"one");
CustomThread thread2=new CustomThread(shared,"two");
CustomThread thread3=new CustomThread(shared,"three");
CustomThread thread4=new CustomThread(shared,"four");
try{
//jion()方法使得當前線程暫停執行,等待調用該方法的線程結束後再繼續執行本線程
thread1.join();
thread2.join();
thread3.join();
thread4.join();
}catch(InterruptedException e){}
}
}
class CustomThread extends Thread{
Shared shared;
public CustomThread(Shared shared,String string){
super(string);
this.shared=shared;
start();
}
public void run(){
//實現同步
shared.doWork(Thread.currentThread().getName());
}
}
class CustomThread2 implements Runnable{
Shared shared;
Thread thread=new Thread();
public CustomThread2(Shared shared,String string){
this.shared=shared;
thread.start();
}
public void join() throws InterruptedException {
// TODO Auto-generated method stub
thread.join();
}
public void run(){
shared.doWork(Thread.currentThread().getName());
}
}
//共享代碼段
class Shared{
synchronized void doWork(String string){
System.out.println("Strating "+string);
try{
Thread.sleep((long)(Math.random()*500));
}catch(InterruptedException e){}
System.out.println("Ending"+string);
}
}
線程間的通信
新建進程1,進程1開始運行,執行getResult(),進程1處於等待狀態
新建進程2,進程2開始運行,執行doWork(),進程2處於睡眠狀態,喚醒進程1,進程1輸出結果
public class communicat {
public static void main(String[] args) {
// TODO Auto-generated method stub
//共享代碼段
Shared shared=new Shared();
//創建進程
CustomThread thread1=new CustomThread(shared,"one");
CustomThread2 thread2=new CustomThread2(shared,"two");
}
}
class CustomThread extends Thread{
Shared shared;
public CustomThread(Shared shared,String string){
super(string);
this.shared=shared;
start();
}
public void run(){
//實現同步
System.out.println(shared.getResult());
}
}
class CustomThread2 extends Thread{
Shared shared;
public CustomThread2(Shared shared,String string){
super(string);
this.shared=shared;
start();
}
public void run(){
//實現同步
shared.doWork();
}
}
//共享代碼段
class Shared{
int data=0;
synchronized void doWork(){
try{
Thread.sleep((1000));
}catch(InterruptedException e){}
data=1;
notify();
}
synchronized int getResult(){
try{
wait();
}catch(InterruptedException e){}
return data;
}
}