20171016-進程、線程問題
====================程序、進程、線程的概念==================
1.程序、進程、線程之間的區別?
進程是具有一定獨立功能的程序關於某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位.
線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源.
相對進程而言,線程是一個更加接近於執行體的概念,它可以與同進程中的其他線程共享數據,但擁有自己的棧空間,擁有獨立的執行序列。
進程和線程的主要差別在於它們是不同的操作系統資源管理方式。進程有獨立的地址空間,一個進程崩潰後,在保護模式下不會對其它進程產生影響,而線程只是一個進程中的不同執行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間
簡而言之,一個程序至少有一個進程,一個進程至少有一個線程.
程序預熱:
首先要明白,如下的程序是不是多線程?
public class MultiThread {
public static void main(String[] args) {
method2();
}
public static void method1(){
System.out.println("Method1執行了!");
}
public static void method2(){
System.out.println("Method2執行了!");
method1();
}
}
Java中多線程的創建和使用
繼承Thread類與實現Runnable接口
1.繼承Thread類
//1實現多線程的第一種方式,繼承Thread類
class SubThread extends Thread{
//需要重寫Run方法
public void run() {
for(int i = 0 ;i <100;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
public class MultiThread {
public static void main(String[] args) {
SubThread subThread = new SubThread();
//開啟線程
//同一個子線程只能被調用一次!
subThread.start();
for(int i = 0 ;i <100;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
用繼承Thread類的方式實現多窗口售票的功能
//1模擬火車站售票窗口,開啟三個窗口售票,總票數為100張
class Window extends Thread{
private static int ticket = 100;
【非靜態的屬性是不能被多個線程共用的!】
public void run(){
while(ticket > 0){
System.out.println(Thread.currentThread().getName()+" 所售票號為:"+(ticket--));
}
}
}
public class MultiThread {
public static void main(String[] args) {
Window w1 = new Window();
Window w2 = new Window();
Window w3 = new Window();
w1.start();
w2.start();
w3.start();
}
}
多線程的第二種實現方式:實現接口的方式
//2.實現線程的第二種方式,實現接口的方式
class SubThread implements Runnable{
@Override public void run() {
for(int i=0 ;i<100;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
public class MultiThread {
public static void main(String[] args) {
SubThread s1 = new SubThread();
Thread t1 = new Thread(s1);
Thread t2 = new Thread(s1);
t1.start();
t2.start();
}
}
//模擬窗口賣票.實現線程的第二種方式,實現接口的方式
class SubThread implements Runnable{
private int ticket = 100;
@Override
public void run() {
while(ticket >0){
System.out.println(Thread.currentThread().getName()+"所出售的票是:"+(ticket--));
}
}
}
public class MultiThread {
public static void main(String[] args) {
SubThread s1 = new SubThread();
Thread t1 = new Thread(s1);
Thread t2 = new Thread(s1);
t1.start();
t2.start();
}
}
對比: 繼承Thread類與實現Runnable接口的方式,哪個實現方式更好一些呢? 實現的方式更優雅一些:
①:避免了java單繼承的局限性
②: 如果多個線程要操作同一份資源(或數據).更適合使用實現的方式。
====================多線程安全問題【演示】========================
//此程序存在線程安全問題,存在重票或者錯票的問題!
class SubThread implements Runnable{
private int ticket = 100;
@Override public void run() {
while(ticket >0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"所出售的票是:"+(ticket--));
}
}
}
public class MultiThread {
public static void main(String[] args) {
SubThread s1 = new SubThread();
Thread t1 = new Thread(s1);
Thread t2 = new Thread(s1);
t1.start();
t2.start();
}
}
//那怎麽處理線程安全的問題呢?
1.首先要知道出現線程安全問題的原因是什麽?
由於一個線程在操作共享數據過程中,未執行完畢的情況下,另外的線程參與進來,導致共享數據存在了安全問題。
2.如何來解決線程的安全問題?
必須讓一個線程操作共享數據完畢之後,其它線程才有機會參與共享數據的操作!
3.Java如何實現線程的安全:線程的同步機制
方式一:同步代碼塊[參考doc文檔]
方式二:同步方法[默認的鎖對象是this關鍵字
]
20171016-進程、線程問題