多線程
優(yōu)點: 解決一個進程同時執(zhí)行多個代碼任務(wù)的問題
自定義線程
方法1: 繼承Thread
- 自定義一個雷繼承
Thread類 - 重寫
Thread的run()方法,多線程代碼在run()中執(zhí)行 - 創(chuàng)建Thread子類對象,并調(diào)用
start()方法啟動一個線程.
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + i);
}
}
}
class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(super.getName() + i);
}
}
Console
main0
Thread-00
main1
Thread-01
main2
Thread-02
main3
方法2: 實現(xiàn)Runnable接口
- 自定義一個類
implements Runnable接口 - 實現(xiàn)
Runnable接口中的run()方法,把自定義線程的任務(wù)代碼定義在run()方法中 - 創(chuàng)建
Runnable實現(xiàn)類的對象 - 創(chuàng)建
Thread對象,并把Runnable實現(xiàn)類的對象作為參數(shù)傳遞 - 調(diào)用
Thread對象的start()方法開啟線程
public static void main(String[] args) {
//MyThread myThread = new MyThread();
//myThread.start();
MyThread2 myThread2 = new MyThread2();
Thread th = new Thread(myThread2);
th.start();
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + i);
}
}
class MyThread2 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + i);
}
}
}
Console
main0
Thread-00
main1
Thread-01
main2
Thread-02
線程安全
弊端:多個線程需要判斷鎖,較為消耗資源
線程安全出現(xiàn)問題原因:
1.必須存在兩個或以上的線程共享著一個資源.
2.操作共享資源的代碼必須有兩句或者兩句以上.
1.同步代碼塊
synchronized(對象){//這個對象可以是任意對象
//需要被同步的代碼
//對象如同鎖,持有鎖的線程可以在同步中執(zhí)行
//沒持有鎖的線程即使獲取CPU的執(zhí)行權(quán),也進不去
}
public static void main(String[] args) {
//MyThread myThread = new MyThread();
//myThread.start();
MyThread2 myThread2 = new MyThread2();
Thread th1 = new Thread(myThread2);
Thread th2 = new Thread(myThread2);
Thread th3 = new Thread(myThread2);
Thread th4 = new Thread(myThread2);
th1.start();
th2.start();
th3.start();
th4.start();
}
class MyThread2 implements Runnable{
Object obj = new Object();
@Override
public void run() {
for (int i = 0; i < 3; i++) {
synchronized (obj) {
System.out.println(Thread.currentThread().getName() +","+ i);
}
}
}
}
Console
Thread-0,0
Thread-0,1
Thread-0,2
Thread-2,0
Thread-2,1
Thread-2,2
Thread-1,0
Thread-1,1
Thread-1,2
Thread-3,0
Thread-3,1
Thread-3,2
2.同步函數(shù)
修飾符 synchronized 返回值類型 函數(shù)名(形參列表...){
}
class Bank{
private int sum = 0;
public synchronized void add(int a){//同步函數(shù)
sum += a;
try{
Thread.sleep(40);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("sum = " + sum);
}
}
class Client implements Runnable{
private Bank b = new Bank();
@Override
public void run(){
for (int i = 0; i < 3; i++) {
b.add(100);
}
}
}
public class ThreadDemo2 {
public static void main(String[] args) {
Client c = new Client();
Thread t1 = new Thread(c);
Thread t2 = new Thread(c);
t1.start();
t2.start();
}
注意 :
- 同步代碼的鎖,可以是任意對象
Object,同步函數(shù)的鎖,是固定的,非靜態(tài)函數(shù)的鎖對象是this,靜態(tài)函數(shù)的鎖對象是class對象 - 同步鎖對象必須是多線程共享的對象,否則鎖不住(鎖唯一)
- 再同步代碼塊或者同步函數(shù)中調(diào)用
sleep方法不會釋放鎖對象,調(diào)用wait方法是會釋放對象的。
給個github follow me的鏈接,上面有很多初學者可供學習的資料,項目.
<a>https://github.com/SuperZee</a>