Java多线程
实现线程的两种方法:
a. 继承Thread类,start()启动。
b. 实现Runnable接口,实现run方法。
1. 基本线程
package com.sam.thread;
public class SimpleThread extends Thread {
private int countDown = 5;
private static int threadCount = 0;
public SimpleThread() {
super(" " + ++threadCount); // store the thread name
start();
}
public String toString() {
return "#" + getName() + ": " + countDown;
}
public void run() {
while (true) {
System.out.println(this);
if (--countDown == 0)
return;
}
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
new SimpleThread();
}
}
}
package com.sam.thread; public class SimpleThread extends Thread { private int countDown = 5; private static int threadCount = 0; public SimpleThread() { super(" " + ++threadCount); // store the thread name start(); } public String toString() { return "#" + getName() + ": " + countDown; } public void run() { while (true) { System.out.println(this); if (--countDown == 0) return; } } public static void main(String[] args) { for (int i = 0; i < 5; i++) { new SimpleThread(); } } }
结果:
# 1: 5 # 1: 4 # 1: 3 # 1: 2 # 1: 1 # 3: 5 # 3: 4 # 3: 3 # 3: 2 # 3: 1 # 2: 5 # 5: 5 # 5: 4 # 5: 3 # 5: 2 # 5: 1 # 2: 4 # 2: 3 # 2: 2 # 2: 1 # 4: 5 # 4: 4 # 4: 3 # 4: 2 # 4: 1
2.yield(),让步,让其它线程使用CPU,可以让结果更均衡。
package com.sam.thread; public class YieldThread extends Thread { private int countDown = 5; private static int threadCount = 0; public YieldThread() { super(" " + ++threadCount); // store the thread name start(); } public String toString() { return "#" + getName() + ": " + countDown; } public void run() { while (true) { System.out.println(this); if (--countDown == 0) return; yield(); } } public static void main(String[] args) { for (int i = 0; i < 5; i++) { new YieldThread(); } } }
结果:
# 1: 5 # 2: 5 # 3: 5 # 1: 4 # 2: 4 # 5: 5 # 3: 4 # 1: 3 # 5: 4 # 3: 3 # 1: 2 # 5: 3 # 3: 2 # 1: 1 # 5: 2 # 4: 5 # 3: 1 # 5: 1 # 2: 3 # 4: 4 # 2: 2 # 2: 1 # 4: 3 # 4: 2 # 4: 1
3. sleep, 休眠一段时间再执行
package com.sam.thread; public class SleepThread extends Thread { private int countDown = 5; private static int threadCount = 0; public SleepThread() { super(" " + ++threadCount); // store the thread name start(); } public String toString() { return "#" + getName() + ": " + countDown; } public void run() { while (true) { System.out.println(this); if (--countDown == 0) return; try { sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void main(String[] args) { for (int i = 0; i < 5; i++) { new SleepThread(); } } }
结果:
# 1: 5 # 3: 5 # 2: 5 # 5: 5 # 4: 5 # 1: 4 # 2: 4 # 4: 4 # 3: 4 # 5: 4 # 1: 3 # 2: 3 # 3: 3 # 4: 3 # 5: 3 # 2: 2 # 4: 2 # 3: 2 # 1: 2 # 5: 2 # 1: 1 # 2: 1 # 4: 1 # 3: 1 # 5: 1
4. 优先级 setPriority();
package com.sam.thread; public class PriorityThread extends Thread { private int countDown = 5; private static int threadCount = 0; public PriorityThread(int priority) { super(" " + ++threadCount); // store the thread name setPriority(priority); start(); } public String toString() { return "#" + getName() + ": " + countDown; } public void run() { while (true) { System.out.println(this); if (--countDown == 0) return; } } public static void main(String[] args) { new PriorityThread(Thread.MAX_PRIORITY); for (int i = 0; i < 5; i++) { new PriorityThread(Thread.MIN_PRIORITY); } } }
结果:优先级高的先运行
# 1: 5 # 1: 4 # 1: 3 # 1: 2 # 1: 1 # 3: 5 # 3: 4 # 3: 3 # 3: 2 # 3: 1 # 5: 5 # 5: 4 # 5: 3 # 5: 2 # 5: 1 # 2: 5 # 2: 4 # 2: 3 # 2: 2 # 2: 1 # 4: 5 # 4: 4 # 4: 3 # 6: 5 # 6: 4 # 6: 3 # 6: 2 # 6: 1 # 4: 2 # 4: 1
5. 后台线程(daemon)
当所有非后台线程结束,线程终止。如:某个时刻线程都sleep了,程序终止。
package com.sam.thread; public class DaemonThread extends Thread { private int countDown = 5; private static int threadCount = 0; public DaemonThread() { super(" " + ++threadCount); // store the thread name setDaemon(true); start(); } public String toString() { return "#" + getName() + ": " + countDown; } public void run() { while (true) { System.out.println(this); if (--countDown == 0) return; try { sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void main(String[] args) { for (int i = 0; i < 5; i++) { new DaemonThread(); } } }
结果:
# 1: 5 # 3: 5 # 5: 5 # 4: 5 # 2: 5
6. join()和interrupt()
package com.sam.thread; class A extends Thread { public A() { start(); } public void run() { try { System.out.println("A started."); sleep(1000); } catch (InterruptedException e) { System.out.println("Sleep interrupted"); } } } public class JoinThread extends Thread { A a; public JoinThread(A a) { this.a = a; start(); } public void run() { try { a.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("JoinThread started."); } public static void main(String[] args) { A a = new A(); JoinThread jt = new JoinThread(a); a.interrupt(); } }
结果:
A started. Sleep interrupted JoinThread started.
7. Runnable接口
package com.sam.thread; public class RunnableThread implements Runnable { private int countDown = 5; public String toString() { return "#" + Thread.currentThread().getName() + ": " + countDown; } @Override public void run() { while (true) { System.out.println(this); if (--countDown == 0) return; } } public static void main(String[] args) { for (int i = 1; i <= 5; i++) { new Thread(new RunnableThread(), "" + i).start(); } } }
runnable接口本身不带线程的特性,要运行,还是要建立一个单独的Thread对象。
8. 不正确地访问资源
package com.sam.thread; public class AlwaysEven { int i; void next() { i++; i++; } int get() { return i; } public static void main(String[] args) { final AlwaysEven ae = new AlwaysEven(); new Thread() { public void run() { while (true) { int j = ae.get(); if (j % 2 != 0) { System.out.println(j); System.exit(0); } } } }.start(); while (true) { ae.next(); } } }
结果:
1501
9. 解决共享资源竞争
在每个访问共享资源的方法上都要加上synchronized,否则不加的方法会忽视该锁。
package com.sam.thread; public class AlwaysEven { int i; synchronized void next() { i++; i++; } synchronized int get() { return i; } public static void main(String[] args) { final AlwaysEven ae = new AlwaysEven(); new Thread() { public void run() { while (true) { int j = ae.get(); if (j % 2 != 0) { System.out.println(j); System.exit(0); } } } }.start(); while (true) { ae.next(); } } }
10. volatile
禁止编译器进行优化,线程不能保留该对象的私有拷贝,影响效率。
11. 临界区
防止多个线程访问方法中的部分代码。
synchronized(syncObject) { // This code can only be access // by one thread at a time }
12. 线程的状态
新建(new)
就绪(Runnable)
死亡(Dead)
阻塞(Blocked)
13. notify()
唤醒wait()中的线程。
zz