??按照萬物皆對象的思想,Java實現(xiàn)創(chuàng)建線程肯定是通過某個類或者某個借口來實現(xiàn)的,也就是說某個類或接口的一個實例就是一個線程。Java中便提供了Runable類和Thread類來幫我們創(chuàng)建線程。
繼承Thread類創(chuàng)建線程
??若某個類想讓它的實例稱為一個線程,繼承Thread類,再覆蓋run()方法即可。
- 創(chuàng)建類
public class ExtThread extends Thread{
public void run() {
for(int i = 0; i < 100; i++) {
System.out.println(this.getName() +" " + i);
}
}
}
- 創(chuàng)建線程
public static void main(String[] args) {
Thread et1 = new ExtThread();
Thread et2 = new ExtThread();
et1.start();
et2.start();
}
實現(xiàn)Runnable接口創(chuàng)建線程
??創(chuàng)建一個類實現(xiàn)Runnable接口,實現(xiàn)的run()方法就是線程中真正執(zhí)行的方法。
- 創(chuàng)建類
public class ImpRunnable implements Runnable {
public void run() {
for(int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " "+i);
}
}
}
- 創(chuàng)建線程
public static void main(String[] args) {
ImpRunnable ir = new ImpRunnable();
Thread t1 = new Thread(ir);
Thread t2 = new Thread(ir);
t1.start();
t2.start();
}
Thread&Runnable
??JDK第一句對Runnable的解釋是:The Runnable interface should be implemented by any class whose instances are intended to be executed by a thread. 所以任何可以創(chuàng)建線程的類都實現(xiàn)了Runnable 接口,Thread也不例外:JDK中:public class Thread implements Runnable { ... }。所以對線程進行操縱的類是Thread類,起核心功能的是Runnable中的run()方法。
??在實際使用時多使用實現(xiàn)Runnable接口創(chuàng)建線程這種方式。因為Java只支持單一繼承,繼承Thread類之后不方便拓展其他功能。
synchronized
??經(jīng)典案例,買票問題。
- 賣票類
public class Ticket implements Runnable{
private int tickets = 100;
public void run() {
while(true) {
if(tickets > 0) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("正在賣第" + tickets-- + "張票");
}else
System.exit(0);
}
}
}
- 三個賣票窗口賣票
public static void main(String[] args) {
Ticket ticket = new Ticket();
//三個買票窗口
Thread t1 = new Thread(ticket);
Thread t2 = new Thread(ticket);
Thread t3 = new Thread(ticket);
t1.start();
t2.start();
t3.start();
}
??執(zhí)行后的結(jié)果發(fā)現(xiàn)有的票被賣了兩次,還賣了不存在的票。
??解決方案,使用同步代碼塊。
public class Ticket implements Runnable{
private int tickets = 100;
Object o = new Object();
public void run() {
synchronized (o) {
while(true) {
if(tickets > 0) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("正在賣第" + tickets-- + "張票");
}else
System.exit(0);
}
}
}
}
??當(dāng)然還可以使用同步方法。
public class Ticket implements Runnable{
private int tickets = 100;
Object o = new Object();
public void run() {
extracted();
}
private synchronized void extracted() {
while(true) {
if(tickets > 0) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("正在賣第" + tickets-- + "張票");
}else
System.exit(0);
}
}
}
??這個時候鎖的是當(dāng)前對象this。如果方法是static的,鎖此類的字節(jié)碼對象。