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