一.線程的創建
1.繼承Thread
public class MyThread extends Thread{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"......run called......");
}
public static void main(String[] args) {
MyThread t0 = new MyThread();
MyThread t1 = new MyThread();
t0.start();
t1.start();
System.out.println(Thread.currentThread().getName()+"......main called......");
}
}
2.實現Runnable接口
當某一個類由父類時,無法繼承Thread類,可通過實現Runnable接口來實現線程創建
public class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"......run called......");
}
public static void main(String[] args) {
MyRunnable r = new MyRunnable();
Thread t0 = new Thread(r);
Thread t1 = new Thread(r);
t0.start();
t1.start();
System.out.println(Thread.currentThread().getName()+"......main called......");
}
}
3.實現細節
public class MyThread {
private Runnable r;
public MyThread(Runnable r) {
this.r = r;
}
public void run(){
}
public void start(){
if(r!=null)
this.run();
}
}
4.Thread和Runnable實現創建線程的區別
- Runnable可避免子類繼承Thread類中除run和start以外的方法
- Runnable可避免java單繼承的缺陷
- Runnable有共享數據
二.線程安全
1.使用Runnable實現賣票(當線程任務執行很快,要想模擬出2個程序同時執行的效果,使用循壞讓程序一直執行)
public class MyRunnable implements Runnable{
private int ticketNo = 100;
@Override
public void run() {
while(true) {
if(ticketNo>0) {
try {
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "賣出了票號爲"+ticketNo+"的票");
ticketNo--;
}
}
}
public static void main(String[] args) {
MyRunnable r = new MyRunnable();
Thread t0 = new Thread(r);
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
Thread t3 = new Thread(r);
t0.start();
t1.start();
t2.start();
t3.start(); }
}
分析出現0,-1,-2以及4個9的原因。
2.線程安全產生的原因
- 多個線程有共享數據
- 操作共享數據的代碼有多份