1. Starting Thread
Two way of starting a thread
a. extends Thread class and override run method
b. implements Runnable interface and pass it as the param of Thread constructor
class RunnerThread extends Thread{
public void run(){
//to do some action
}
}
class RunnerRunnable implements Runnable{
public void run(){
//to do some action
}
}
public class BasicApp {
public static void main(String[] args) {
RunnerThread t1 = new RunnerThread();
t1.start();
RunnerRunnable runnerRunnable = new RunnerRunnable();
Thread t2 = new Thread(runnerRunnable);
Thread t3 = new Thread(new Runnable(){
public void run(){
//to do some action
}
});
t2.start();
t3.start();
}
}
2. Basic-Thread-Synchronization
volatile关键字保证缓存中的值被更新
import java.util.Scanner;
class Runner implements Runnable{
volatile boolean runFlag = true;
public void run() {
while(runFlag){
System.out.println("Running");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void setRunFlag(boolean runFlag){
this.runFlag = runFlag;
}
}
public class App2 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
Runner runner = new Runner();
Thread t1 = new Thread(runner);
t1.start();
scan.nextLine();
runner.setRunFlag(false);
scan.close();
}
}
3. The synchronized keyword
public class App3 {
private int count = 0;
synchronized private void increment(){
count++;
}
public static void main(String[] args) throws InterruptedException {
App3 app3 = new App3();
app3.doWork();
}
private void doWork() throws InterruptedException{
Thread t1 = new Thread(new Runnable() {public void run() {for(int i=0; i<1000; i++) increment();}});
Thread t2 = new Thread(new Runnable() {public void run() {for(int i=0; i<1000; i++) increment();}});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Count="+ count);
}
}
4. Multiple Locks; Using Synchronized Code Blocks
class Process implements Runnable{
private ArrayList<Integer> list1 = new ArrayList<Integer>();
private ArrayList<Integer> list2 = new ArrayList<Integer>();
private Random random = new Random();
private Object obj1 = new Object();
private Object obj2 = new Object();
private void addList1() throws InterruptedException{
synchronized(obj1){
list1.add(random.nextInt(100));
}
Thread.sleep(1);
}
private void addList2() throws InterruptedException{
synchronized(obj2){
list2.add(random.nextInt(100));
}
Thread.sleep(1);
}
public void run(){
for(int i=0; i<1000; i++){
try {
addList1();
addList2();
} catch (InterruptedException e) {
}
}
}
public void showSize(){
System.out.println("List1:"+ list1.size() +",List2:"+ list2.size());
}
}
public class App4 {
public static void main(String[] args) throws InterruptedException {
StopWatch stopWatch = new StopWatch("App4");
stopWatch.start();
Process proc = new Process();
Thread t1 = new Thread(proc);
Thread t2 = new Thread(proc);
t1.start();
t2.start();
t1.join();
t2.join();
stopWatch.stop();
proc.showSize();
System.out.println(String.format("App4 takes %d miliseconds", stopWatch.getTotalTimeMillis()));
}
}
运行结果:
List1:2000,List2:2000
App4 takes 2016 miliseconds
不加synchronized关键字的运行结果:
List1:1981,List2:1988
App4 takes 2018 miliseconds
将synchronized关键字加在方法上的运行结果:
List1:2000,List2:2000
App4 takes 4093 miliseconds
private synchronized void addList1() throws InterruptedException{
list1.add(random.nextInt(100));
Thread.sleep(1);
}
private synchronized void addList2() throws InterruptedException{
list2.add(random.nextInt(100));
Thread.sleep(1);
}
5. Thread Pools
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
class Runner1 implements Runnable{
private int id;
public Runner1(final int i){
this.id = i;
}
public void run(){
System.out.println("Starting:"+ id);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
System.out.println("Complete:"+ id);
}
}
public class App5 {
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(2); //设置2个线程池,重复使用,减少建立线程的开销
for(int i=0; i<5; i++){
executor.submit(new Runner1(i)); //提交任务
}
executor.shutdown(); //提交任务结束,等待线程结束,此后不允许再提交
System.out.println("All tasks submitted.");
executor.awaitTermination(1, TimeUnit.MINUTES); //若线程运行时间过长,会在此时间后结束
System.out.println("All tasks completed.");
}
}
6. CountDown latches
class Process implements Runnable{
private CountDownLatch latch;
public Process(final CountDownLatch latch){
this.latch = latch;
}
public void run(){
System.out.println("Start, count="+ latch.getCount());
latch.countDown();
}
}
public class App6 {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(9); //CountDownLatch class is thread-safe
ExecutorService executor = Executors.newFixedThreadPool(3);
for(int i=0; i<20; i++){
executor.submit(new Process(latch));
}
executor.shutdown();
latch.await(); //thread will wait until the count of latch become 0
System.out.println("Complete.");
}
}
运行结果:
Start, count=9
Start, count=8
Start, count=7
Start, count=6
Start, count=5
Start, count=4
Start, count=3
Start, count=2
Start, count=1
Start, count=0
Start, count=0
Start, count=0
Start, count=0
Start, count=0
Start, count=0
Start, count=0
Start, count=0
Start, count=0
Start, count=0
Complete. //总是会在count=0之后
Start, count=0
7. Producer-Consumer
BlockingQueue是Thread-Safe, 达到max size后不再添加元素,size为0时不能再take
public class App7 {
private static BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10);
private static void producer() throws InterruptedException{
Random random = new Random();
while(true){
Thread.sleep(500);
queue.put(random.nextInt(100));
}
}
private static void consumer() throws InterruptedException{
Random random = new Random();
while(true){
Thread.sleep(100);
if(random.nextInt(10) == 0){
int value = queue.take();
System.out.println("Taken value="+ value + ", Queue Size="+ queue.size());
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
public void run() {
try {
producer();
} catch (InterruptedException e) {
}
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
try {
consumer();
} catch (InterruptedException e) {
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}
8. wait and notify
package demo1;
import java.util.Scanner;
class Processor8{
public void producer() throws InterruptedException{
System.out.println("Thread start...");
synchronized(this){
wait();
}
System.out.println("Resumed.");
}
public void consumer() throws InterruptedException{
Thread.sleep(1000);
Scanner scan = new Scanner(System.in);
System.out.println("Press enter to be continue...");
scan.nextLine();
synchronized(this){
notify(); //唤醒在wait此object的线程,被唤醒的线程必须在此object被释放后才能继续运行
Thread.sleep(2500);
}
if(scan!=null)scan.close();
}
}
public class App8 {
public static void main(String[] args) throws InterruptedException {
final Processor8 proc = new Processor8();
Thread t1 = new Thread(new Runnable() {
public void run() {
try {proc.producer();} catch (InterruptedException e) {}
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
try {proc.consumer();} catch (InterruptedException e) {}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}
9. A Worked Example Using Low-Level Synchronization
class Processor9 {
private LinkedList<Integer> list = new LinkedList<Integer>();
private final int LIMIT = 10;
private Object lock = new Object();
private Random random = new Random();
public void producer() throws InterruptedException {
int value = 0;
while (true) {
synchronized (lock) {
System.out.println("producer");
while (list.size() == LIMIT) {
lock.wait();
}
list.add(value++);
lock.notify();
}
}
}
public void consumer() throws InterruptedException {
while (true) {
synchronized (lock) {
System.out.println("consumer");
while (list.size() == 0) {
lock.wait();
}
System.out.print("List size:" + list.size());
int value = list.removeFirst();
System.out.println(", taken value:" + value);
lock.notify();
}
Thread.sleep(random.nextInt(1000));
}
}
}
public class App9 {
public static void main(String[] args) throws InterruptedException {
final Processor9 proc = new Processor9();
Thread t1 = new Thread(new Runnable() {
public void run() {
try {
proc.producer();
} catch (InterruptedException e) {
}
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
try {
proc.consumer();
} catch (InterruptedException e) {
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}
10. Re-entrant Locks
import java.util.Scanner;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
class Processor10 {
private ReentrantLock lock = new ReentrantLock();
Condition cond = lock.newCondition();
private int count = 0;
public void increment(){
for(int i=0; i<100000000; i++){
count++;
}
}
public void firstThread() {
lock.lock(); //类比synchronized关键字
System.out.println("Waiting...");
try {
cond.await(); //类比object.wait();
System.out.println("Wake up...");
increment();
} catch (InterruptedException e) {
System.out.println("Error1:"+ e.getMessage());
}finally{
lock.unlock();
}
}
public void secondThread() {
Scanner scan = null;
try{
Thread.sleep(1000);
lock.lock(); //类比synchronized关键字
System.out.println("Press enter to continue...");
scan = new Scanner(System.in);
scan.nextLine();
cond.signal(); //类比object.notify();
increment();
}catch(Exception e){
System.out.println("Error2:"+ e.getMessage());
}finally{
lock.unlock();
if(scan!=null)scan.close();
}
}
public void finish(){
System.out.println("Count is:"+ count);
}
}
public class App10 {
public static void main(String[] args) throws InterruptedException {
final Processor10 proc = new Processor10();
Thread t1 = new Thread(new Runnable() {
public void run() {
proc.firstThread();
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
proc.secondThread();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
proc.finish();
}
}
11. Dead lock
class Account{
private int deposit = 10000;
private void deposit(final int amount){
this.deposit += amount;
}
private void withdraw(final int amount){
this.deposit -= amount;
}
public static void transfer(final Account acc1, final Account acc2, final int amount){
acc1.withdraw(amount);
acc2.deposit(amount);
}
public int getDeposit(){
return this.deposit;
}
}
class Runner11{
Random random = new Random();
Account acc1 = new Account();
Account acc2 = new Account();
Lock lock1 = new ReentrantLock();
Lock lock2 = new ReentrantLock();
public void firstThread(){
for(int i=0; i<1000000; i++){
try{
accquireLock(lock1, lock2);
Account.transfer(acc1, acc2, random.nextInt(1000));
}catch(Exception e){
}finally{
lock1.unlock();
lock2.unlock();
}
}
}
public void secondThread(){
for(int i=0; i<1000000; i++){
try{
accquireLock(lock2, lock1);
Account.transfer(acc2, acc1, random.nextInt(1000));
}catch(Exception e){
}finally{
lock1.unlock();
lock2.unlock();
}
}
}
public void finish(){
System.out.println("Account1 Amount:"+ acc1.getDeposit());
System.out.println("Account2 Amount:"+ acc2.getDeposit());
System.out.println("Total Amount:"+ (acc1.getDeposit() + acc2.getDeposit()));
}
public void accquireLock(Lock lock1, Lock lock2) throws InterruptedException{
//2个锁同时获得才返回,否则将获得的单个锁释放以让其他线程获得
boolean lock1Status = false;
boolean lock2Status = false;
while(true){
try{
lock1Status = lock1.tryLock();
lock2Status = lock2.tryLock();
}finally{
if(lock1Status && lock2Status){
return;
}
if(lock1Status){
lock1.unlock();
}
if(lock2Status){
lock2.unlock();
}
}
Thread.sleep(10);
}
}
}
public class App11 {
public static void main(String[] args) throws InterruptedException {
final Runner11 runner = new Runner11();
Thread t1 = new Thread(new Runnable() {
public void run() {
runner.firstThread();
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
runner.secondThread();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
runner.finish();
}
}
12. Semaphores
Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源
class Runner12{
private int connCnt = 0;
private Semaphore sem = new Semaphore(10); //限制同时只能连10个
public void getConnection(){
try{
sem.acquire();
synchronized (this) {
connCnt++;
}
System.out.println("Current connection is :"+ connCnt);
Thread.sleep(50);
synchronized (this) {
connCnt--;
}
}catch(Exception e){
}
finally{
sem.release();
}
}
}
public class App12 {
public static void main(String[] args) throws InterruptedException {
final Runner12 runner = new Runner12();
ExecutorService executor = Executors.newFixedThreadPool(10);
for(int i=0; i<1000; i++){
executor.submit(new Runnable() {
public void run() {
runner.getConnection();
}
});
}
executor.shutdown();
executor.awaitTermination(100, TimeUnit.SECONDS);
}
}
13. Callable and Future
public class App13 {
public static void main(String[] args) throws InterruptedException, ExecutionException {
final Random random = new Random();
ExecutorService executor = Executors.newCachedThreadPool();
//Callable不同于Runnable,可以有返回值,并可抛出异常
Future<Integer> future = executor.submit(new Callable<Integer>(){
public Integer call() throws InterruptedException{
int duration = random.nextInt(4000);
System.out.println("Start...");
Thread.sleep(duration);
System.out.println("Done.");
return duration;
}
});
executor.shutdown();
executor.awaitTermination(1, TimeUnit.MINUTES);
//Future用于获取线程的返回值,状态等信息
System.out.println("Takes "+ future.get() + " miliseconds.");
}
}
14. Interrupting Threads
a. use interrupt method
public class App14 {
public static void main(String[] args) throws InterruptedException {
System.out.println("Start...");
Thread t = new Thread(new Runnable() {
public void run() {
Random random = new Random();
for(int i=0; i<1E8; i++){
if(Thread.interrupted()){
System.out.println("Interrupted...");
break;
}
Math.sin(random.nextDouble());
}
}
});
t.start();
t.interrupt();
t.join();
System.out.println("End.");
}
}
b. use future.cancel()
public class App14 {
public static void main(String[] args) throws InterruptedException {
System.out.println("Start...");
ExecutorService exec = Executors.newCachedThreadPool();
Future<?> fu = exec.submit(new Callable<Void>(){
public Void call(){
Random random = new Random();
for(int i=0; i<1E8; i++){
if(Thread.interrupted()){
System.out.println("Interrupted...");
break;
}
Math.sin(random.nextDouble());
}
return null;
}
});
exec.shutdown();
fu.cancel(true); //1. true表示开始的线程也结束 2. false表示只结束未开始的
exec.awaitTermination(1, TimeUnit.MINUTES);
System.out.println("End.");
}
}
c. use ExecutorService的shutdownNow()
public class App14 {
public static void main(String[] args) throws InterruptedException {
System.out.println("Start...");
ExecutorService exec = Executors.newCachedThreadPool();
exec.submit(new Callable<Void>(){
public Void call(){
Random random = new Random();
for(int i=0; i<1E8; i++){
if(Thread.interrupted()){
System.out.println("Interrupted...");
break;
}
Math.sin(random.nextDouble());
}
return null;
}
});
exec.shutdown();
exec.shutdownNow();
exec.awaitTermination(1, TimeUnit.MINUTES);
System.out.println("End.");
}
}