Java 多线程

介绍Java中多线程。

Runnable & Thread

Thread类中的start方法通知线程规划器此线程已经就绪,等待调用线程对象的run方法。

使用run方法是同步的,此线程对象并不会交给线程规划器来进行处理,而是由当前主线程来同步执行。

使用start方法是同步的,但系统调用run方法的过程是异步执行,因此线程执行与start的顺序是不一致的。

java不支持多继承,对于已有父类的继承类来说,需要实现Runnable接口来实现线程类。

1
2
3
4
5
6
7
8
9
10
11
12
public static class RunnableHello extends MyHello implements Runnable {
@Override
public void run() {
// do something
}
}

public static void test1() {
RunnableHello runnableHello = new RunnableHello();
Thread thread = new Thread(runnableHello);
thread.start();
}

synchronized

synchronized关键字能够保证在同一时刻最多只有一个线程执行该段代码。

synchronized可用于标记对象代码块函数等。

1
2
3
synchronized(someObj) { // dosomething }
sychronized(this) { // dosomething}
synchronized public void method() { // dosomething }

interrupt

interrupt:用于停止当前线程,不会立刻停止,而是先给当前线程打一个中断标记。

interrupted:测试当前线程是否已经中断状态,执行后清除状态标识为false

isInterrupted:测试当前线程是否已经中断状态,不清除状态标识。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 观察打印结果
public static class ExtendsThread1 extends Thread {

@Override
public void run() {
try {
for (int i = 0; i < 5000; i++) {
Thread.sleep(1000);
if (this.isInterrupted()) {
System.out.println("interrupted");
return;
}
System.out.println(i);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

public static void test2() {
ExtendsThread1 thread1 = new ExtendsThread1();
thread1.start();
Thread.sleep(2000);
thread1.interrupt();
}

suspend

suspend用于暂停线程,但已经废弃了。

废弃原因:使用suspend和resume方法容易因为线程暂定导致数据不同步的情况,会造成死锁。

yield

yeild用于放弃当前占用的CPU资源,但放弃的时间不确定,下一次获得CPU的占用权的时间同样不能确定。

yeild特性:

  • 静态的原生(native)方法;
  • 状态切换的非实时性
  • 当前正在执行的线程把运行机会交给线程池中拥有相同优先级的线程;
  • 它仅能使一个线程从运行状态转到可运行状态,而不是等待或阻塞状态。

priority

setPriority方法可以用来设置线程的优先级,优先级高的线程更容易获得CPU的执行权

java中线程优先级分为1~10,默认定义:

1
2
3
public final static int MIN_PRIORITY = 1;
public final static int NORM_PRIORITY = 5;
public final static int MAX_PRIORITY = 10;

线程的优先级是可继承的

daemon

java中可以通过setDaemon方法设置守护线程

守护线程是一种特殊的线程,只有当JVM停止运行时,该线程才会被结束。例如,垃圾回收器就是一个用于回收内存对象的守护线程