1.什麼是進程、線程 進程可以簡單的理解為應用程式。多線程,相當於多個人共同完成一件事情,每個線程,獨立完成一件任務。因此,一個進程至少有一個線程,一個線程不能獨立存在,它必須是進程的一部分。 進程:每個獨立運行著的程式。具有獨立的記憶體空間和系統資源。(建大廈) 線程:是一個進程內部的一條執行路徑。 ...
1.什麼是進程、線程
進程可以簡單的理解為應用程式。多線程,相當於多個人共同完成一件事情,每個線程,獨立完成一件任務。因此,一個進程至少有一個線程,一個線程不能獨立存在,它必須是進程的一部分。
進程:每個獨立運行著的程式。具有獨立的記憶體空間和系統資源。(建大廈)
線程:是一個進程內部的一條執行路徑。是系統獨立調度和分配CPU的最小單位。(搬磚頭)
2.創建線程的方式(三種)
- 1.通過實現 Runnable 介面;(存在共用資源時使用——是否是相同操作)
- 2.通過繼承 Thread 類本身;(沒有共用資源時可用)
- 3.通過 Callable 和 Future 創建線程。(JDK1.5開始引入)
對比:
-
1. 採用實現 Runnable、Callable 介面的方式創建多線程時,線程類只是實現了 Runnable 介面或 Callable 介面,還可以繼承其他類。
-
2. 使用繼承 Thread 類的方式創建多線程時,編寫簡單,如果需要訪問當前線程,則無需使用 Thread.currentThread() 方法,直接使用 this 即可獲得當前線程。
3.線程的狀態及特性
線程具有隨機性:誰能搶到CPU,誰執行。
package com.test;
public class ThreadDemo1 { public static void main(String[] args) { // TODO Auto-generated method stub MyThread myThread=new MyThread("name"); //myThread.run();//主線程 myThread.start();//多線程 } } class MyThread extends Thread{ public MyThread() { super(); // TODO Auto-generated constructor stub } public MyThread(String name) { super(name); } public void run() { for(int i=0;i<20;i++) { System.out.println(Thread.currentThread().getName()+"→"+i); } } }
創建線程,輸出1~100之間的偶數。要求使用線程實現,繼承Thread類
package com.test; public class ThreadDemo2 { public static void main(String[] args) { // TODO Auto-generated method stub OutputEven outputEven=new OutputEven(); outputEven.start(); } } class OutputEven extends Thread{ @Override public void run() { // TODO Auto-generated method stub for(int i=1;i<=100;i++) { if(i%2==0) { System.out.println(Thread.currentThread().getName()+"→"+i); } } } }
使用線程模擬四個工人搬磚場景,誰搶到托運機誰去搬磚
package com.test; public class ThreadDemo3 { public static void main(String[] args) { // TODO Auto-generated method stub Worker worker1=new Worker("張三1","搬磚"); Worker worker2=new Worker("張三2","搬磚"); Worker worker3=new Worker("張三3","搬磚"); Worker worker4=new Worker("張三4","搬磚"); worker1.start(); worker2.start(); worker3.start(); worker4.start(); } } class Worker extends Thread{ String name; String task; public Worker() { // TODO Auto-generated constructor stub super(); } public Worker(String name, String task) { super(); this.name = name; this.task = task; } @Override public void run() { // TODO Auto-generated method stub work(); } public void work() { System.out.println(name+"正在"+task); } }
三個視窗都可以賣100張票。
package com.test; public class ThreadDemo4 { public static void main(String[] args) { // TODO Auto-generated method stub WinTicket winTicket1=new WinTicket("視窗1"); WinTicket winTicket2=new WinTicket("視窗2"); WinTicket winTicket3=new WinTicket("視窗3"); winTicket1.start(); winTicket2.start(); winTicket3.start(); } } class WinTicket extends Thread{ private int ticket=100; public WinTicket() { super(); // TODO Auto-generated constructor stub } public WinTicket(String name) { super(name); } @Override public void run() { // TODO Auto-generated method stub while(true) { if(ticket>0) { String name=Thread.currentThread().getName(); System.out.println(name+"賣出"+ticket--); }else { break; } } } }
4.多個線程共用資源
三個視窗共同賣100張票。
package com.test; public class ThreadDemo5 { public static void main(String[] args) { // TODO Auto-generated method stub //創建共用資源對象 TicketRes ticketRes=new TicketRes(); //創建線程對象 Thread w1=new Thread(ticketRes,"視窗1"); Thread w2=new Thread(ticketRes,"視窗2"); Thread w3=new Thread(ticketRes,"視窗3"); w1.start(); w2.start(); w3.start(); } } //共用資源類 class TicketRes implements Runnable{ private int ticket=100; @Override public void run() { // TODO Auto-generated method stub while(true) { if(ticket>=1) { System.out.println(Thread.currentThread().getName()+"賣第"+ticket+"張票"); ticket--; }else { break; } } } } //出現一個問題:第一百張票會同時在三個視窗賣出。這個涉及到同步和非同步的問題?該怎麼解決呢?Java多線程基礎(二)揭曉答案
5.線程調度
優先順序
優先順序用1-10表示,1的優先順序最低,10的優先順序最高,預設情況為5
setPriority(int grade);
調度方法
join():阻塞指定的線程等到另一個線程完成以後再執行
package com.test; public class JoinDemo { public static void main(String[] args) throws InterruptedException { // TODO Auto-generated method stub System.out.println("主線程在執行..."); JoinThread joinThread1=new JoinThread("線程1"); JoinThread joinThread2=new JoinThread("線程2"); JoinThread joinThread3=new JoinThread("線程3"); System.out.println("啟動子線程..."); joinThread1.start(); joinThread2.start(); joinThread3.start(); joinThread1.join(); joinThread2.join(); joinThread3.join(); for(int i=0;i<10;i++) { System.out.println("主線程正在執行..."); } System.out.println("結束"); } } class JoinThread extends Thread{ public JoinThread() { super(); // TODO Auto-generated constructor stub } public JoinThread(String name) { super(name); // TODO Auto-generated constructor stub } @Override public void run() { // TODO Auto-generated method stub for(int i=0;i<10;i++) { System.out.println(Thread.currentThread().getName()+"→"+i); } } }View Code
sleep():會暫時釋放CPU, 讓給其他線程執行, 即使沒有其他線程搶占CPU,也需要等待睡眠時間到了以後才能真正的指定
package com.test; public class SleepDemo { public static void main(String[] args){ // TODO Auto-generated method stub SleepThread sleepThread=new SleepThread(); sleepThread.start(); } } class SleepThread extends Thread{ public SleepThread() { super(); // TODO Auto-generated constructor stub } public SleepThread(String name) { super(name); // TODO Auto-generated constructor stub } @Override public void run() { // TODO Auto-generated method stub for(int i=10;i>=0;i--) { try { Thread.sleep(1000); System.out.println(i); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }View Code
yield():執行的時候會讓出CPU , 但是會立馬同其他的線程搶占CPU
package com.test; public class YieldDemo { public static void main(String[] args) { // TODO Auto-generated method stub YieldThread yieldThread1=new YieldThread("線程1"); YieldThread yieldThread2=new YieldThread("線程2"); yieldThread1.start(); yieldThread2.start(); } } class YieldThread extends Thread{ public YieldThread() { super(); // TODO Auto-generated constructor stub } public YieldThread(String name) { super(name); // TODO Auto-generated constructor stub } @Override public void run() { // TODO Auto-generated method stub for(int i=0;i<20;i++) { System.out.println(Thread.currentThread().getName()+"→"+i); Thread.yield();//避讓,謙讓,讓出CPU,還有再去搶的資格 } } }View Code