一個程序至少有一個進程,一個進程至少有一個線程.
進程是程序在一個數據集合上的運行過程。它是系統進行資源分配和調度的一個獨立單位。
線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。
關於進程的使用,可以限制進程的數量,我覺得這是一個例子,比如有的程序它不允許你多客戶端運行,如夢幻西遊,它能限制你的客戶端數量,可能就是從進程方面來做的,再比如LOL ,它只允許你運行一個客戶端。
區別:
進程和線程的主要差別在於它們是不同的操作系統資源管理方式。進程有獨立的地址空間,一個進程崩潰後,在保護模式下不會對其它進程產生影響,而線程只是一個進程中的不同執行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等於整個進程死掉,所以多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。但對於一些要求同時進行並且又要共享某些變量的併發操作,只能用線程,不能用進程。
1) 簡而言之,一個程序至少有一個進程,一個進程至少有一個線程.
2) 線程的劃分尺度小於進程,使得多線程程序的併發性高。
3) 另外,進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,從而極大地提高了程序的運行效率。
4) 線程在執行過程中與進程還是有區別的。每個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。但是線程不能夠獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。
5) 從邏輯角度來看,多線程的意義在於一個應用程序中,有多個執行部分可以同時執行。但操作系統並沒有將多個線程看做多個獨立的應用,來實現進程的調度和管理以及資源分配。這就是進程和線程的重要區別。
爲什麼要用多線程?
由於Java採用的是單線程編程模型,因此在進行UI編程時要注意將耗時的操作放在子線程中進行,以避免阻塞主線程(在UI編程時,主線程即UI線程,用來處理用戶的交互事件)
我們平時習慣的主函數就是一個線程,這個時候,如果我們在主函數中有一個非常耗時的操作,比如連接網絡,連接數據庫,或者大量的計算等等,在主函數的主線程中執行這些操作,帶來的後果將是,在這些耗時操作完成之前,其他操作無法進行。比如在這個耗時操作之後有繪製UI的操作,這個時候,很可能會等上十幾秒UI才能顯示出來,這樣的結果肯定會非常不好。
那麼爲了解決上述問題,我們就要使用多線程,在主線程外設置一個子線程,這樣把耗時操作放在子線程中,主線程中運行一些簡單的操作,如UI繪製等,這樣就不會出現顯示UI卡死的狀況。
java中使用多線程 有兩種方法: 繼承Thread類, 實現Runable接口。
1
/**
* 因爲輸出10個數比較小,當你啓動啓動第二個線程時第一個線程已經運行完畢,
* 所以兩次輸出都是順序輸出,要麼將i設置很大很大,要麼讓每次打印暫停一下
* @author Administrator
*
*/
public class ThreadTest {
public static void main(String[] args) {
MyThread mt1 = new MyThread("線程A");
MyThread mt2 = new MyThread("線程B");
mt1.start();
mt2.start();
}
}
class MyThread extends Thread {
private String name;
public MyThread(String name) {
this.name = name;
}
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(name + "運行,i=" + i);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
2
/**
* 兩個線程不一定誰先執行
* @author Administrator
*
*/
public class RunableTest {
public static void main(String[] args) {
System.out.println("主線程ID:" + Thread.currentThread().getId());
MyRunableThread runableThread1 = new MyRunableThread("線程1");
MyRunableThread runableThread2 = new MyRunableThread("線程2");
Thread thread1 = new Thread(runableThread1);
Thread thread2 = new Thread(runableThread2);
thread2.start();
thread1.run();
}
}
class MyRunableThread implements Runnable {
String name;
public MyRunableThread(String string) {
this.name = string;
}
@Override
public void run() {
System.out.println("子線程ID:" + name + ": " + Thread.currentThread().getId());
}
}
通過start()方法去啓動線程。注意,不是調用run()方法啓動線程,run方法中只是定義需要執行的任務,如果調用run方法,即相當於在主線程中執行run方法,跟普通的方法調用沒有任何區別,此時並不會創建一個新的線程來執行定義的任務。
1)thread1和thread2的線程ID不同,thread2和主線程ID相同,說明通過run方法調用並不會創建新的線程,而是在主線程中直接運行run方法,跟普通的方法調用沒有任何區別;
2)雖然thread1的start方法調用在thread2的run方法前面調用,但是先輸出的是thread2的run方法調用的相關信息,說明新線程創建的過程不會阻塞主線程的後續執行。