Java 中的多线程
参考资料:
《Java SE 6.0 编程指南》作者:吴亚峰 纪超 出版社:人民邮电出版社
1、线程对象的创建和启动
package com.aimartt.thread;
/**
* 自定义类1,实现 Runnable 接口
*/
class MyThread1 implements Runnable {
//实现 run 方法
@Override
public void run() {
for (int i = 0; i < 13; i++) {
System.out.print("[" + i + "]");
}
}
}
/**
* 自定义类2,继承 Thread 类
*/
class MyThread2 extends Thread {
//重写 run 方法
@Override
public void run() {
for (int i = 0; i < 13; i++) {
System.out.print("<" + i + ">");
}
}
}
/**
* 主类
*/
public class Demo {
/**
* 主方法
* @param args
*/
public static void main(String[] args) {
//创建线程对象
Thread thread1 = new Thread(new MyThread1());
Thread thread2 = new Thread(new MyThread2());
//启动线程
thread1.start();
thread2.start();
}
}
□ 两个线程都启动后,各自的执行时间和执行顺序是没有保证的。
2、线程的调度
2.1、睡眠
以下代码中,两个线程将交替执行:
package com.aimartt.thread;
/**
* 自定义类1,实现 Runnable 接口
*/
class MyThread1 implements Runnable {
//实现 run 方法
@Override
public void run() {
for (int i = 0; i < 19; i++) {
System.out.print("[" + i + "]");
try {
Thread.sleep(100); //此线程睡眠 100 毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 自定义类2,继承 Thread 类
*/
class MyThread2 extends Thread {
//重写 run 方法
@Override
public void run() {
for (int i = 0; i < 19; i++) {
System.out.print("<" + i + ">");
try {
Thread.sleep(100); //此线程睡眠 100 毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 主类
*/
public class Demo {
/**
* 主方法
* @param args
*/
public static void main(String[] args) {
//创建线程对象
Thread thread1 = new Thread(new MyThread1());
Thread thread2 = new Thread(new MyThread2());
thread1.start(); //启动线程1
try {
Thread.sleep(10); //主线程睡眠 10 毫秒,让线程1先执行
} catch (InterruptedException e) {
e.printStackTrace();
}
thread2.start(); //启动线程2
}
}
□ 线程醒来将进入准备状态,不能保证被立即执行,因此指定的时间是线程睡眠的最小时间。
2.2、线程的优先级
Java中线程的优先级用1到10的整数表示,数值越大,优先级越高,默认为5。对于子线程,其优先级与父线程相同。
以下代码中,优先级高的线程尽可能的先执行(单核CPU):
package com.aimartt.thread;
/**
* 自定义类1,实现 Runnable 接口
*/
class MyThread1 implements Runnable {
//实现 run 方法
@Override
public void run() {
for (int i = 0; i < 21; i++) {
System.out.print("[" + i + "]");
}
}
}
/**
* 自定义类2,继承 Thread 类
*/
class MyThread2 extends Thread {
//重写 run 方法
@Override
public void run() {
for (int i = 0; i < 21; i++) {
System.out.print("<" + i + ">");
}
}
}
/**
* 主类
*/
public class Demo {
/**
* 主方法
* @param args
*/
public static void main(String[] args) {
//创建线程对象
Thread thread1 = new Thread(new MyThread1());
Thread thread2 = new Thread(new MyThread2());
//设置两个线程的优先级
thread1.setPriority(Thread.MAX_PRIORITY);
thread2.setPriority(Thread.MIN_PRIORITY);
//启动两个线程
thread1.start();
thread2.start();
}
}
□ 当前正在执行的线程的优先级一般不会低于等待执行的线程,但不是绝对的。
2.3、线程的让步
2.3.1、使用 yield() 方法
使当前正在运行的线程让出CPU,回到准备状态。
注意:当前运行的线程回到准备状态后有可能立即被在再次调度进入运行状态,所以 yield() 方法让步不一定成功。例子如下:
package com.aimartt.thread;
/**
* 自定义类1,实现 Runnable 接口
*/
class MyThread1 implements Runnable {
//实现 run 方法
@Override
public void run() {
for (int i = 0; i < 9; i++) {
System.out.print("[" + i + "]");
Thread.yield(); //当前线程让步
}
}
}
/**
* 自定义类2,继承 Thread 类
*/
class MyThread2 extends Thread {
//重写 run 方法
@Override
public void run() {
for (int i = 0; i < 9; i++) {
System.out.print("<" + i + ">");
Thread.yield(); //当前线程让步
}
}
}
/**
* 主类
*/
public class Demo {
/**
* 主方法
* @param args
*/
public static void main(String[] args) {
//创建线程对象
Thread thread1 = new Thread(new MyThread1());
Thread thread2 = new Thread(new MyThread2());
//启动两个线程
thread1.start();
thread2.start();
}
}
2.3.2、使用 join() 方法
当一个线程必须等待另一个线程执行完毕才恢复执行时,可以使用此方法。
使用 join() 方法进行两个线程之间的让步是有保证的,被让步的线程在未执行完之前,被让步的线程是不会恢复执行的。例子如下:
package com.aimartt.thread;
/**
* 自定义类1,实现 Runnable 接口
*/
class MyThread1 implements Runnable {
//实现 run 方法
@Override
public void run() {
for (int i = 0; i < 9; i++) {
System.out.print("[" + i + "]");
}
System.out.println("\n子线程执行结束");
}
}
/**
* 主类
*/
public class Demo {
/**
* 主方法
* @param args
*/
public static void main(String[] args) {
//创建线程对象
Thread thread1 = new Thread(new MyThread1());
thread1.start();
for (int i = 0; i < 54; i++) {
if (i == 15) {
System.out.println("\n使用 join() 方法让主线程让步");
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print("<" + i + ">");
}
}
}