Java_多线程
線程要依附進程存在
多線程的實現一定要有一個線程的主類,而主類往往需要操作一些資源,但對于多線程主類的實現有一定的要求:
1. 繼承Thread父類;
2. 實現Runnable接口(Callable接口)
繼承Thread類實現多線程:
在java.lang包有Thread類,子類繼承Thread后要覆寫Thread類中的run()方法,這個方法就屬于線程的主方法。
?定義:public void run();
范例:線程的主體類;
class MyThread extends Thread{ //表示實現多線程private String name;public MyThread(String name) { //線程的名字this.name = name;}@Overridepublic void run() { //覆寫run()方法,線程的主方法for(int x = 0; x < 10; x++) {System.out.println(this.name + ", x = " + x);}} }上面是將內容輸出10次,所有的線程并發執行,即在一個時間段上會有多個線程交替執行,所以不能直接調用run方法,而應該調用Thread類中的start()方法啟動多線程。
public void start()
范例:啟動多線程?
class MyThread extends Thread{ //表示實現多線程private String name;public MyThread(String name) { //線程的名字this.name = name;}@Overridepublic void run() { //覆寫run()方法,線程的主方法for(int x = 0; x < 10; x++) {System.out.println(this.name + ", x = " + x);}} } public class Hello{public static void main(String[] args) {MyThread mt1 = new MyThread("線程A");MyThread mt2 = new MyThread("線程B");MyThread mt3 = new MyThread("線程C");mt1.start();mt2.start();mt3.start();} }結果混亂,是因為交替執行,沒有固定的執行順序。若不調用start而調用run,就是順序執行?
?
實現Runnable接口
繼承Thread會有單繼承的局限,所以最好的做法是利用接口來解決,于是使用Runnable接口。
public interface Runnable {public void run(); }按照正常思路實現Runnable多線程:
class MyThread implements Runnable{ //表示實現多線程private String name;public MyThread(String name) { //線程的名字this.name = name;}@Overridepublic void run() { //覆寫run()方法,線程的主方法for(int x = 0; x < 10; x++) {System.out.println(this.name + ", x = " + x);}} }此時如果想開始多線程,由于現在實現的是Runnable接口,所以無法用Thread類中的start方法了,現在使用匿名內部類來使用start方法
class MyThread implements Runnable{ //表示實現多線程private String name;public MyThread(String name) { //線程的名字this.name = name;}@Overridepublic void run() { //覆寫run()方法,線程的主方法for(int x = 0; x < 10; x++) {System.out.println(this.name + ", x = " + x);}} } public class Hello{public static void main(String[] args) {MyThread mt1 = new MyThread("線程A");MyThread mt2 = new MyThread("線程B");MyThread mt3 = new MyThread("線程C");new Thread(mt1).start(); //匿名new Thread(mt2).start();new Thread(mt3).start();} }?
面試題
繼承Thread類和Runnable接口兩種實現方式的區別:
多線程一定需要一個線程的主類,要么繼承Thread類,要么實現Runnable接口
使用Runnable接口可以比Thread更好實現數據共享操作,利用Runnable接口可以避免單繼承局限問題
Thread類實現了Runnable接口。
Runnable接口實現的多線程要比Thread類實現的多線程更方便的表現出數據共享的概念
范例:希望有三個線程進行買票 - Thread實現會發現三個線程各自賣各自的票,票沒有了其他線程也不知道
class MyThread extends Thread{ //表示實現多線程private int ticket = 5;@Overridepublic void run() { //覆寫run()方法,線程的主方法for(int x = 0; x < 50; x++) {if(this.ticket>0) {System.out.println("賣票,ticket = " + this.ticket --);}}} } public class Hello{public static void main(String[] args) {MyThread mt1 = new MyThread();MyThread mt2 = new MyThread();MyThread mt3 = new MyThread();mt1.start();mt2.start();mt3.start();} }?
使用Runnable接口實現:
class MyThread implements Runnable{ //表示實現多線程private int ticket = 5;@Overridepublic void run() { //覆寫run()方法,線程的主方法for(int x = 0; x < 50; x++) {if(this.ticket>0) {System.out.println("賣票,ticket = " + this.ticket --);}}} } public class Hello{public static void main(String[] args) {MyThread mt = new MyThread();new Thread(mt).start();new Thread(mt).start();new Thread(mt).start();} }?
Callable接口:
比Runnable的好處是可以返回值
class MyThread implements Callable<String>{ //表示實現多線程private int ticket = 5;@Overridepublic String call() { //覆寫run()方法,線程的主方法for(int x = 0; x < 50; x++) {if(this.ticket>0) {System.out.println("賣票,ticket = " + this.ticket --);}}return "票賣完了";} } public class Hello{public static void main(String[] args) throws InterruptedException, ExecutionException {Callable<String> cal = new MyThread();FutureTask<String> task = new FutureTask<>(cal);Thread thread = new Thread(task);thread.start();System.out.println(task.get()); //取得線程主方法的返回值 } }?
線程休眠
可以讓某些線程延緩執行
休眠方法:public static void sleep (long millis) throws InterruptedException;
如果休眠時間沒到就停止休眠了,那么就會產生中斷異常。
Thread.sleep(1000);? 加上這一句,延遲一秒,會有報錯,點報錯糾錯就對了
class MyThread implements Runnable{ //表示實現多線程 @Overridepublic void run() { //覆寫run()方法,線程的主方法for(int x = 0; x < 100; x++) {try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch block e.printStackTrace();} //休眠一秒System.out.println(Thread.currentThread().getName() + ", x = " + x);}} } public class Hello{public static void main(String[] args) throws InterruptedException, ExecutionException {MyThread mt = new MyThread();new Thread(mt, "線程A").start();new Thread(mt, "線程B").start();new Thread(mt, "線程C").start();} }?
線程的優先級
優先級越高的線程越有可能先執行,而在Thread類定義一下優先級方法
設置優先級:public final void setPriority(int newPriority);
取得優先級:public final int getPriority();
優先級定義有三種:
最高優先級:public static final int MAX_PRIORITY,10;
中等優先級:public static final int NORM_PRIORITY,5;
最低優先級:public static final int MIN_PRIORITY,1;
class MyThread implements Runnable{ @Overridepublic void run() { for(int x = 0; x < 100; x++) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();} System.out.println(Thread.currentThread().getName() + ", x = " + x);}} } public class Hello{public static void main(String[] args) throws InterruptedException, ExecutionException {MyThread mt = new MyThread();Thread t1 = new Thread(mt, "線程A");Thread t2 = new Thread(mt, "線程B");Thread t3 = new Thread(mt, "線程C");t1.setPriority(Thread.MAX_PRIORITY);t2.setPriority(Thread.MIN_PRIORITY);t3.setPriority(Thread.MIN_PRIORITY);t1.start();t2.start();t3.start();} }設置優先級只是理論上的,不一定真的就是優先
?
范例:主線程的優先級是什么
public class Hello{public static void main(String[] args) throws InterruptedException, ExecutionException {System.out.println(Thread.currentThread().getPriority());} }結果是5,主線程屬于中等優先級
總結:
線程要有名字,Thread.currentThread取得當前線程;
線程的休眠有先后順序
優先級越高理論上越有可能先執行
?
線程同步,多線程需要訪問同一資源
同步代碼塊:使用synchronized關鍵字定義的代碼塊就是同步代碼塊,但同步的時候需要設置一個同步對象,往往使用this同步當前對象。
范例:買票,買票最后票的數量不能出現負數
class MyThread implements Runnable{private int ticket = 50;@Overridepublic void run() {for(int x = 0; x < 100; x ++) {synchronized (this) { //同步代碼塊if(this.ticket > 0) {try {Thread.sleep(100); //延遲一秒 }catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + ", ticket = " + this.ticket --);}}}} }public class Hello{public static void main(String[] args) throws Exception {MyThread mt = new MyThread();Thread t1 = new Thread(mt,"票販子A");Thread t2 = new Thread(mt,"票販子B");Thread t3 = new Thread(mt,"票販子C");t1.start();t2.start();t3.start();} }?另一種實現方式,synchronized方法
class MyThread implements Runnable{private int ticket = 5;@Overridepublic void run() {for(int x = 0; x < 10; x ++) {this.sale();}}public synchronized void sale() { //賣票if(this.ticket > 0) {try {Thread.sleep(100); //延遲一秒 }catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + ", ticket = " + this.ticket --);}} }public class Hello{public static void main(String[] args) throws Exception {MyThread mt = new MyThread();Thread t1 = new Thread(mt,"票販子A");Thread t2 = new Thread(mt,"票販子B");Thread t3 = new Thread(mt,"票販子C");t1.start();t2.start();t3.start();} }?
轉載于:https://www.cnblogs.com/lonske/p/8798235.html
總結
- 上一篇: Module(模块)
- 下一篇: UVA11825 Hackers' Cr