java線程之基礎學習總結
線程實現的兩種方式:
在java中可以有兩種方式實現多線程操作,一種是繼承Thread類,另外一種是實現Runnable接口。
繼承Thread類
Thread類是在java.lang包中定義的
一個類只要繼承Thread類,要覆寫run()方法。
簡單實例
定義MyThread類
- 定義MyThread類
- public class MyThread extends Thread {
- private String name;
- public MyThread(String name) {
- this.name = name;
- }
- public void run() {
- for (int i = 0; i < 5; i++) {
- System.out.println(name + "運行:" + i);
- }
- }
- }
編寫TestThread類調用:
- public class TestThread {
- public static void main(String[] args) {
- MyThread myThread1 = new MyThread("singsong1");
- MyThread myThread2 = new MyThread("singsong2");
- myThread1.run();
- myThread2.run();
- }
- }
- 運行結果:
- singsong1運行:0
- singsong1運行:1
- singsong1運行:2
- singsong1運行:3
- singsong1運行:4
- singsong2運行:0
- singsong2運行:1
- singsong2運行:2
- singsong2運行:3
- singsong2運行:4
從結果可以發現,此時的執行非常的有規律,先執行完第一個對象,再執行第二個對象。
把run()方法換成start();一旦調用start()方法,則會通過JVM找到run()方法
Public void start()
使用start()方法啓動線程:
- public class TestThread {
- public static void main(String[] args) {
- MyThread myThread1 = new MyThread("singsong1");
- MyThread myThread2 = new MyThread("singsong2");
- myThread1.start();
- myThread2.start();
- }
- }
- 運行結果:
- singsong1運行:0
- singsong1運行:1
- singsong2運行:0
- singsong1運行:2
- singsong2運行:1
- singsong1運行:3
- singsong2運行:2
- singsong1運行:4
- singsong2運行:3
- singsong2運行:4
從運行結果可以知道,程序時交互式的運行。
因爲需要用到CPU的資源,所以每次的運行結果基本是都不一樣的
不要調用Thread類或Runnable對象的run方法。直接調用run方法,只會執行同一個線程中的任務,而不會啓動新線程。應該調用Thread.start()方法。這個方法將創建一個執行run方法的新線程。
Runnable接口的實現
簡單實例
- public class RunnableThread implements Runnable {
- private String name;
- public RunnableThread(String name) {
- this.name = name;
- }
- public void run() {
- for (int i = 0; i < 5; i++) {
- System.out.println(name + "運行:" + i);
- }
- }
- }
編寫TestThread1調用
- public class TestThread1 {
- public static void main(String[] args) {
- RunnableThread runnableThread1=new RunnableThread("singsong1");
- RunnableThread runnableThread2=new RunnableThread("singsong2");
- Thread thread1= new Thread(runnableThread1);
- Thread thread2= new Thread(runnableThread2);
- thread1.start();
- thread2.start();
- }
- }
- 運行結果:
- singsong1運行:0
- singsong1運行:1
- singsong2運行:0
- singsong2運行:1
- singsong2運行:2
- singsong2運行:3
- singsong2運行:4
- singsong1運行:2
- singsong1運行:3
- singsong1運行:4
Thread類和Runnable接口區別
最大區別是在於資源的共享
如果一個類繼承Thread,則資源共享不可共享。而實現Runable接口,能實現資源共享。
例如:
MyThread類
- public class MyThread extends Thread {
- private int ticket = 5;
- private String name;
- public MyThread(String name) {
- this.name = name;
- }
- public void run() {
- for (int i = 0; i < 15; i++) {
- if (ticket > 0) {
- System.out.println(name + "正售出第 " + (ticket--) + "票");
- }
- }
- }
- }
- 調用:
- public class TestThread {
- public static void main(String[] args) {
- MyThread myThread1 = new MyThread("singsong1");
- MyThread myThread2 = new MyThread("singsong2");
- myThread1.start();
- myThread2.start();
- }
- }
- 運行結果:
- singsong1正售出第 5票
- singsong1正售出第 4票
- singsong1正售出第 3票
- singsong1正售出第 2票
- singsong1正售出第 1票
- singsong2正售出第 5票
- singsong2正售出第 4票
- singsong2正售出第 3票
- singsong2正售出第 2票
- singsong2正售出第 1票
重複售出了一次
再來看看Runnable接口是怎麼實現資源共享的
RunnableThread類
- public class RunnableThread implements Runnable {
- private int ticket = 5;
- private String name;
- public RunnableThread(String name) {
- this.name = name;
- }
- public void run() {
- for (int i = 10; i > 0; i--) {
- if (ticket > 0) {
- System.out.println(name + "正售出第 " + (ticket--) + "票");
- }
- }
- }
- }
編寫TestThread1類調用:
- public class TestThread1 {
- public static void main(String[] args) {
- RunnableThread runnableThread1 = new RunnableThread("singsong1");
- Thread thread1 = new Thread(runnableThread1);
- Thread thread2 = new Thread(runnableThread1);
- thread1.start();
- thread2.start();
- }
- }
- 運行結果:
- singsong1正售出第 5票
- singsong1正售出第 4票
- singsong1正售出第 3票
- singsong1正售出第 2票
- singsong1正售出第 1票
從運行結果可以得出實現Runnable接口的優點。
大家有沒有想過Runnable接口爲什麼能實現資源的共享,而Thread類不能
本人個人理解
首先看如下代碼:
- public class TestThread1 {
- public static void main(String[] args) {
- RunnableThread runnableThread1 = new RunnableThread("singsong1");
- RunnableThread runnableThread2 = new RunnableThread("singsong2");
- Thread thread1 = new Thread(runnableThread1);
- Thread thread2 = new Thread(runnableThread2);
- thread1.start();
- thread2.start();
- }
- }
此代碼是在TestThread1類的繼承上修改的:添加了 RunnableThread runnableThread2 = new RunnableThread("singsong2");
把runnableThread1換成runnableThread2
現在我們在運行程序看看結果:
- singsong1正售出第 5票
- singsong1正售出第 4票
- singsong1正售出第 3票
- singsong1正售出第 2票
- singsong1正售出第 1票
- singsong2正售出第 5票
- singsong2正售出第 4票
- singsong2正售出第 3票
- singsong2正售出第 2票
- singsong2正售出第 1票
從結果可以知道也重複了一次。
總結一下:也是就說Runnable接口能實現資源的共享是因爲用同一個實現Runnable接口的子類來創建不同的線程,去執行同一個任務。而Thread卻沒有這種機制。