1) Sleep
package edu.xmu.thread;
public class SleepTest
{
public static void main(String[] args)
{
Thread thread1 = new Thread(new MyRunnable());
Thread thread2 = new Thread(new MyRunnable());
Thread thread3 = new Thread(new MyRunnable());
System.out.println(System.currentTimeMillis());
thread1.start();
thread2.start();
thread3.start();
System.out.println(System.currentTimeMillis());
}
private static class MyRunnable implements Runnable
{
@Override
public void run()
{
try
{
System.out.println(Thread.currentThread().getName()
+ " is going to sleep.");
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
Output:
1400034838666
Thread-0 is going to sleep.
1400034838666
Thread-1 is going to sleep.
Thread-2 is going to sleep.
// We can see that static method Thread.sleep() will sleep the current thread.
Attention:
System.out.println(System.currentTimeMillis());
thread1.start();
thread2.start();
thread3.start();
thread3.sleep(1000);
System.out.println(System.currentTimeMillis());
// Output:
//1400035177744
//Thread-0 is going to sleep.
//Thread-1 is going to sleep.
//Thread-2 is going to sleep.
//1400035178744
// The thread3.sleep(1000); will not make thread3 sleep.
// It will make current main thread sleep instead.
// So we can find out that although threadInstance.sleep() is applicable,
// it will make the current thread instead of threadInstance sleep.
// Pay attention to this pitfall.
2) Join
Example below:
package edu.xmu.thread;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
public class ThreadTest
{
public static void main(String[] args)
{
List<CalculationThread> subThreadList = initSubThreadList();
List<Integer> numList = new ArrayList<Integer>();
for (CalculationThread calThread : subThreadList)
{
calThread.start(); // Start all calculation thread
}
try
{
System.out.println("Current Time Mills: "
+ Calendar.getInstance().getTimeInMillis());
for (CalculationThread calThread : subThreadList)
{
calThread.join();
}
System.out.println("Current Time Mills: "
+ Calendar.getInstance().getTimeInMillis());
CalculationThread sumThread = new CalculationThread();
for (CalculationThread subThread : subThreadList)
{
numList.add(subThread.getSum());
}
sumThread.setNumList(numList);
sumThread.start();
sumThread.join();
System.out.println("Current Time Mills: "
+ Calendar.getInstance().getTimeInMillis());
System.out.println(sumThread.getSum());
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
private static List<CalculationThread> initSubThreadList()
{
CalculationThread thread1 = new CalculationThread(Arrays.asList(200,
200, 200, 200));
CalculationThread thread2 = new CalculationThread(Arrays.asList(300,
300, 300, 300));
CalculationThread thread3 = new CalculationThread(Arrays.asList(300,
300, 300, 300));
CalculationThread thread4 = new CalculationThread(Arrays.asList(300,
300, 300, 300));
CalculationThread thread5 = new CalculationThread(Arrays.asList(300,
300, 300, 300));
List<CalculationThread> subThreadList = new ArrayList<CalculationThread>();
subThreadList.add(thread1);
subThreadList.add(thread2);
subThreadList.add(thread3);
subThreadList.add(thread4);
subThreadList.add(thread5);
return subThreadList;
}
}
class CalculationThread extends Thread
{
private List<Integer> numList;
private int sum;
public CalculationThread()
{
super();
}
public CalculationThread(List<Integer> numList)
{
super();
this.numList = numList;
}
@Override
public void run()
{
try
{
Thread.sleep(2000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
for (int i : numList)
{
sum += i;
}
}
public int getSum()
{
return sum;
}
public void setNumList(List<Integer> numList)
{
this.numList = numList;
}
}
Output:
Current Time Mills: 1400033660648
Current Time Mills: 1400033662639
Current Time Mills: 1400033664640
5600
// We can find out the total subCalculation time cost is: 2000ms.
// So we can use this kind of technique(join method) to divide
// a huge task into several sub-task and start all the sub-task at once
// The main thread will wait till all the sub-task done and then gather
// all the result together.
Example2: For special requirement that a list of threads run sequentially.
package edu.xmu.thread;
public class SequenceThreadTest {
public static void main(String[] args) throws InterruptedException {
Thread sequenceThread = new Thread(new SequenceThread(),
"sequenceThread");
Thread sequenceThread2 = new Thread(new SequenceThread(),
"sequenceThread2");
Thread sequenceThread3 = new Thread(new SequenceThread(),
"sequenceThread3");
Thread sequenceThread4 = new Thread(new SequenceThread(),
"sequenceThread4");
sequenceThread.start();
sequenceThread.join(); // The caller thread(Main thread) will block until sequenceThread finished.
sequenceThread2.start();
sequenceThread2.join();// The caller thread(Main thread) will block until sequenceThread2 finished.
sequenceThread3.start();
sequenceThread3.join();// The caller thread(Main thread) will block until sequenceThread3 finished.
sequenceThread4.start();
sequenceThread4.join();// The caller thread(Main thread) will block until sequenceThread4 finished.
System.out.println("Finished");
}
}
class SequenceThread implements Runnable {
@Override
public void run() {
try {
Thread.sleep((long) (1000 * Math.random()));
System.out
.println("Thread: " + Thread.currentThread()
+ " is running(). Timestamp: "
+ System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Output:
Thread: Thread[sequenceThread,5,main] is running(). Timestamp: 1401247052161
Thread: Thread[sequenceThread2,5,main] is running(). Timestamp: 1401247052625
Thread: Thread[sequenceThread3,5,main] is running(). Timestamp: 1401247053363
Thread: Thread[sequenceThread4,5,main] is running(). Timestamp: 1401247054014
Finished
Another Approach:
package edu.xmu.thread;
public class SequenceThreadTest {
public static void main(String[] args) throws InterruptedException {
Thread sequenceThread = new Thread(new SequenceThread(null),
"sequenceThread");
Thread sequenceThread2 = new Thread(new SequenceThread(sequenceThread),
"sequenceThread2");
Thread sequenceThread3 = new Thread(
new SequenceThread(sequenceThread2), "sequenceThread3");
Thread sequenceThread4 = new Thread(
new SequenceThread(sequenceThread3), "sequenceThread4");
sequenceThread.start();
System.out.println("sequenceThread started. Timestamp: "
+ System.currentTimeMillis());
sequenceThread2.start();
System.out.println("sequenceThread2 started. Timestamp: "
+ System.currentTimeMillis());
sequenceThread3.start();
System.out.println("sequenceThread3 started. Timestamp: "
+ System.currentTimeMillis());
sequenceThread4.start();
System.out.println("sequenceThread4 started. Timestamp: "
+ System.currentTimeMillis());
sequenceThread4.join();
System.out
.println("Finished. Timestamp: " + System.currentTimeMillis());
}
}
class SequenceThread implements Runnable {
Thread previousThread;
public SequenceThread(Thread previousThread) {
super();
this.previousThread = previousThread;
}
@Override
public void run() {
try {
if (previousThread != null) {
previousThread.join(); // The caller thread(current thread) will block until previousThread finished. And main thread will not blocked.
}
Thread.sleep((long) (1000 * Math.random()));
System.out
.println("Thread: " + Thread.currentThread()
+ " is running(). Timestamp: "
+ System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Output:
sequenceThread started. Timestamp: 1401247481556
sequenceThread2 started. Timestamp: 1401247481556
sequenceThread3 started. Timestamp: 1401247481556
sequenceThread4 started. Timestamp: 1401247481556
Thread: Thread[sequenceThread,5,main] is running(). Timestamp: 1401247482485
Thread: Thread[sequenceThread2,5,main] is running(). Timestamp: 1401247482935
Thread: Thread[sequenceThread3,5,main] is running(). Timestamp: 1401247483014
Thread: Thread[sequenceThread4,5,main] is running(). Timestamp: 1401247483916
Finished. Timestamp: 1401247483916
// We can see that MainThread will not block.