例子来源: Youtube-cave of programming
create thread
class Runner extends Thread {
public void run() {
}
}
Runner runner1 = new Runner();
runner1.start();
class Runner implements Runnable {
@Override
public void run() {
}
}
Thead t1 = new Thread(new Runner());
t1.start();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
}
});
volatile keyword
- The value of the variable will never be cached-locally: all reads and writes will go straight to “main memory”;
- Access to the variable acts as though it is enclosed in a synchronized block, sychronized on itself. Reads and writes are atomic for this variable.
class Processor extends Thread {
// use volatile to prevent thread from caching the variable
private volatile boolean running = true;
public void run() {
while(running) {
System.out.println("Hello");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void shutdown() {
running = false;
}
}
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Processor proc1 = new Processor();
proc1.start();
System.out.println("Press enter to stop:");
Scanner scanner = new Scanner(System.in);
scanner.nextLine();
proc1.shutdown();
}
}
synchronized method
When a thread invokes a synchronized method, it automatically acquires the intrinsic lock for that method’s object and release it when the method returns.
- First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
- Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.
public class synchronizedDemo {
private int count = 0;
//make a atomic method, lock the method, only one thread can call it at the same time
//same threads will share the method
public synchronized void increment() {
count++;
}
public static void main(String[] args) {
synchronizedDemo demo = new synchronizedDemo();
demo.doWork();
}
public void doWork() {
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
for(int i=0; i < 10000; i++) {
increment();
}
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
for(int i=0; i < 10000; i++) {
increment();
}
}
});
t1.start();
t2.start();
try {
//wait thread to die
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Count:" + count);
}
}
synchronized block
The update to list1 and list2 can happen simultaneously.
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Worker {
private Object lock1 = new Object();
private Object lock2 = new Object();
private Random random = new Random();
private List<Integer> list1 = new ArrayList<Integer>();
private List<Integer> list2 = new ArrayList<Integer>();
public void stageOne() {
synchronized(lock1){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
list1.add(random.nextInt(100));
}
}
public void stageTwo() {
synchronized(lock2){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
list2.add(random.nextInt(100));
}
}
public void process() {
for(int i = 0; i < 1000 ; i++) {
stageOne();
stageTwo();
}
}
public void main() {
System.out.println("Starting ...");
long start = System.currentTimeMillis();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
process();
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
process();
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("Running time: " + (end - start));
System.out.println("length of list1: "+ list1.size());
System.out.println("length of list2: "+ list2.size());
};
}
ThreadPool
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
class Processor implements Runnable {
private int id;
public Processor(int id) {
this.id = id;
}
@Override
public void run() {
System.out.println("Starting: " + this.id);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Completed: "+ this.id);
}
}
public class App {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(2);
for(int i = 0; i < 5; i++) {
executor.submit(new Processor(i));
}
//do not accept more tasks
executor.shutdown();
System.out.println("all tasks submitted.");
try {
//wait till all tasks are done
executor.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("All tasks completed.");
}
}