java學習筆記(20-多執行緒)
阿新 • • 發佈:2019-01-10
1. Thread類
1.1 繼承實現
package com.daigua20; public class ThreadDemo { public static void main(String[] args) { MyThread t1 = new MyThread(); // 修改執行緒名字 t1.setName("呆瓜"); // 啟動任務 t1.start(); MyThread t2 = new MyThread(); // 修改執行緒名字 t2.setName("豬娃"); // 啟動任務 t2.start(); } } class MyThread extends Thread { @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println(getName() + ":" + i); } } }
1.2 Runnable介面實現
package com.daigua20; public class ThreadDemo2 { public static void main(String[] args) { // 例項出Runnable介面子類的物件 MyThread2 r1 = new MyThread2(10); MyThread2 r2 = new MyThread2(10); // 用Runnable子類構造Thread類的例項 Thread t1 = new Thread(r1); Thread t2 = new Thread(r2); // start方法啟動任務 t1.start(); t2.start(); } } // 定義Runnable介面的子類,重寫run方法 class MyThread2 implements Runnable { int num; public MyThread2(int num) { this.num = num; } @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + ":" + i + num); } } }
2.執行緒安全
2.1 資源共享導致的問題
package com.daigua20; public class ThreadDemo3 { public static void main(String[] args) { TicketThread r1 = new TicketThread(); Thread t1 = new Thread(r1); Thread t2 = new Thread(r1); Thread t3 = new Thread(r1); t1.start(); t2.start(); t3.start(); } } class TicketThread implements Runnable { // 車票數量一百張 int tickets = 100; @Override public void run() { while (true) { if (tickets > 0) { try { Thread.sleep(100); tickets -= 1; } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":" + tickets); } } } }
2.2解決方法
2.2.1 使用同步程式碼塊
格式:
synchronized(鎖物件){
//需要同步的程式碼
}
package com.daigua20;
/*
* synchronized:同步(鎖),可以修飾程式碼塊和方法,被修飾的程式碼塊和方法一旦被某個執行緒訪問,則直接鎖住,其他的執行緒將無法訪問
*
* 同步程式碼塊:
* synchronized(鎖物件){
*
* }
*
* 注意:鎖物件需要被所有的執行緒所共享
*
*
* 同步:安全性高,效率低
* 非同步:效率高,但是安全性低
*
*/
public class ThreadDemo4 {
public static void main(String[] args) {
TicketThread2 r1 = new TicketThread2();
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r1);
Thread t3 = new Thread(r1);
t1.setName("視窗1");
t2.setName("視窗2");
t3.setName("視窗3");
t1.start();
t2.start();
t3.start();
}
}
class TicketThread2 implements Runnable {
// 車票數量一百張
int tickets = 100;
Object obj = new Object();
@Override
public void run() {
while (true) {
synchronized (obj) {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + tickets--);
}
}
}
}
}
2.2.2 使用同步方法
格式:
修飾符 synchronized 返回值 方法名(){
}
package com.daigua20;
/*
* 同步方法:使用關鍵字synchronized修飾的方法,一旦被一個執行緒訪問,則整個方法全部鎖住,其他執行緒則無法訪問
*
* synchronized
* 注意:
* 非靜態同步方法的鎖物件是this
* 靜態的同步方法的鎖物件是當前類的位元組碼物件
*/
public class ThreadDemo5 {
public static void main(String[] args) {
TicketThread3 tt = new TicketThread3();
Thread t1 = new Thread(tt);
Thread t2 = new Thread(tt);
Thread t3 = new Thread(tt);
t1.setName("視窗1");
t2.setName("視窗2");
t3.setName("視窗3");
t3.start();
t2.start();
t1.start();
}
}
class TicketThread3 implements Runnable {
// 車票數量一百張
static int tickets = 100;
// Object obj = new Object();
@Override
public void run() {
while (true) {
if (tickets > 0) {
// method();
method2();
}
}
}
private synchronized void method(){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + tickets--);
}
private static synchronized void method2(){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + tickets--);
}
}