1.实现Runnable接口
//Implement the interface Runnable, while the Runnable only have one abstract run() method, So all the thread that implement Runnable cant return the run() method result and also cant throw the pre defined exception
// Test Class
public class Ticket {
Lock reentrantLocaLock = new ReentrantLock();
static int total;
static {
total = 50;
}
private static Ticket ticket;
public synchronized static Ticket getInstance() {
if(ticket ==null) {
ticket = new Ticket();
}
return ticket;
}
public void sellTicket() {
while (true) {
reentrantLocaLock.lock();
try {
if (Ticket.total > 0) {
Ticket.total--;
System.out.println(Thread.currentThread().getName() + " sold one ticket, and tickets remain "
+ Ticket.total);
} else {
System.out.println(Thread.currentThread().getName() + " Sorry, tickets sold out,tickets remain "
+ Ticket.total);
break;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
reentrantLocaLock.unlock();
// to fast for the cpu, we need to manually switch thread
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
//Thread
public class MyThreadImpl implements Runnable {
@Override
public void run() {
Ticket ticket = Ticket.getInstance();
ticket.sellTicket();
}
}
------
public class ThreadTest {
public static void main(String[] args) {
MyThreadImpl threadImpl =new MyThreadImpl();
for(int i=1;i<4;i++){
new Thread(threadImpl,"Thread-R"+i).start();
}
}
}
1.实现Runnbale接口创建线程更加符合面向对象的特点,在实际情况中多使用这种方式创建线程
2.此种方式实现线程,在线程执行结束后不会有返回值
2.继承自Thread类
// Class Ticket refer to the Impl module code
public class MyThreadExt extends Thread{
//Because the class Thread also impl the inteface Runnable, So there is not big diff between Impl
@Override
public void run() {
Ticket ticket = Ticket.getInstance();
ticket.sellTicket();
}
}
---------
//Thread test
public class ThreadTest {
public static void main(String[] args) {
MyThreadExt threadExt =new MyThreadExt();
for(int i=1;i<4;i++){
new Thread(threadExt,"Thread-E"+i).start();
}
}
}
1. 通过继承Thread类来实现线程的方式虽然可用,但却不太符合面向对象的特点,一般不使用此方式实现线程
2. 此种方式实现线程,在线程执行结束后不会有返回值
3.实现Callable接口
//The the diff between inteface Callable and Runnable are Callable can return the result when a thread end of run, And also can return the pre defined Exceprion
// Class Ticket refer to the Impl module code
public class MyThreadCallable implements Callable<Object> {
@Override
public Object call() throws Exception {
Ticket ticket = Ticket.getInstance();
ticket.sellTicket();
return null;
}
}
-----
//Thread test
public class ThreadTest {
public static void main(String[] args) {
Callable callable=new MyThreadCallable();
FutureTask ftask=new FutureTask(callable);
for(int i=0;i<4;i++){
new Thread(ftask,"Thread-C"+i).start();
}
}
}
1. 实现Callable接口创建线程与实现Runnable接口类似,都符合面向对象特点
2. 实现Callable接口创建线程允许在线程执行结束后存在返回值
4.使用线程池
-------------
//Thread test
public class ThreadTest {
public static void main(String[] args) {
Callable callable=new MyThreadCallable();
MyThreadImpl threadImpl =new MyThreadImpl();
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(3);
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
ExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(3);
ExecutorService newWorkStealingPool = Executors.newWorkStealingPool();
// exec thread without return
newFixedThreadPool.execute(threadImpl);
// exec thread have return
newFixedThreadPool.submit(threadImpl);
//close the thread pool
newFixedThreadPool.shutdown();
}
}
1. 使用线程池可以在各种场景下更加合理的运用多线程
2. execute() 针对的是没有不需要返回结果的线程执行,submit() 作用于有返回结果的线程执行