一、多線程的隨機性
1.多線程是異步的,代碼順序並非線程執行順序,線程被調用的時機是隨機的。
public class MyThread extends Thread {
@Override
public void run() {
super.run();
System.out.println("MyThread");
}
}
public class MultiProcess {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
System.out.println(Thread.currentThread().getName());
}
}
運行結果:先打印了main函數的name,後執行start()方法
備註:
- Thread.java類中的start方法:
通知線程規劃期此線程已經ready,go!坐等cpu調度,執行run方法執行。即異步執行。
- Thread.java類中的run方法:
run方法是同步執行,由main主線程來調度run方法,必須等run中的代碼執行完畢,纔可以執行後邊代碼
二、多線程的兩種實現方式
1.繼承Thread類
public class MyThread extends Thread {
private int i;
public MyThread(int i) {
super();
this.i = i;
}
@Override
public void run() {
super.run();
System.out.println(i);
}
}
public class MultiProcess {
public static void main(String[] args) {
MyThread t1 = new MyThread(1);
MyThread t2 = new MyThread(11);
MyThread t3 = new MyThread(111);
MyThread t4 = new MyThread(1111);
MyThread t5 = new MyThread(11111);
MyThread t6 = new MyThread(111111);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
System.out.println(Thread.currentThread().getName());
}
}
2.實現Runnable接口
public class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("運行中~");
}
}
public static void runnableTest(){
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);//可傳thread或者runnable對象,交由別的線程調用
thread.start();
}
public static void main(String[] args) {
// threadTest();
runnableTest();
System.out.println(Thread.currentThread().getName());
}
備註:Thread構造函數 ,可傳Runnable或者Thread對象,將該對象的run方法交給別的線程調用
3.實例變量與線程安全
3.1 線程間不共享變量
每個線程都有自己的count變量,不共享
public class ThreadA extends Thread{
private int count = 5;
public ThreadA(String name) {
super();
this.setName(name);
}
@Override
public void run() {
super.run();
while (count > 0){
count--;
System.out.println(this.currentThread().getName() + "計算,count = "+count);
}
}
}
public static void notShareVariable(){
ThreadA a = new ThreadA("A"); //每個線程有自己的count
ThreadA b = new ThreadA("B");
ThreadA c = new ThreadA("C");
a.start();
b.start();
c.start();
}
3.2 多個線程共享一個變量
多個線程共享一個變量,就會出現線程不安全問題
public static void shareVariable(){
ThreadA a = new ThreadA();
Thread thread1 = new Thread(a, "A");
Thread thread2 = new Thread(a, "B");
Thread thread3 = new Thread(a, "C");
thread1.start();
thread2.start();
thread3.start();
}
3.3 synchronized關鍵字
解決多線程共享變量時不安全問題,在線程的run方法前加synchronized關鍵字,加鎖,使該部分代碼變成互斥區或臨界區,依次排隊進行操作。
public class ThreadA extends Thread {
private int count = 5;
public ThreadA(String name) {
super();
this.setName(name);
}
public ThreadA() {
}
@Override
synchronized public void run() {
super.run();
count--;
System.out.println(this.currentThread().getName() + "計算,count = " + count);
}
}
//線程間共享變量
public static void shareVariable(){
ThreadA a = new ThreadA();
Thread thread1 = new Thread(a, "A");
Thread thread2 = new Thread(a, "B");
Thread thread3 = new Thread(a, "C");
Thread thread4 = new Thread(a, "D");
Thread thread5 = new Thread(a, "E");
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread5.start();
}