单线程与多线程

单线程: 在任意一个时间点,正在执行程序的主体只有一个
多线程: 在任意一个时间点, 正在运行的程序主体有多个
程序的终止: java程序的终止是指除守护线程(Daemon Thread)以外的线程全部终止。 守护线程是执行后台作用的线程。通过setDaemon方法把线程设置设置为守护线程

start方法的作用

  1. 启动新线程
  2. 新线程调用run方法

启动多线程的两种方式

利用Thread类的子类的实例启动线程

Thread类本身实现了Runnable接口,并且持有run方法,但Thread类的run方法主体是空的,不执行任何操作。Thread类的run方法通常都是由子类的run方法重写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class MyThread extends Thread {

String message;

public MyThread(String message){
this.message = message;
}

@Override
public void run() {
for (int i=0; i<10; i++){
System.out.println(message);
try {
System.out.println("休眠一下");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

运行:
new MyThread("hello").start();

利用Runnable接口的实现类启动线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

class MyRunable implements Runnable{
String message;

public MyRunable(String message){
this.message = message;
}

@Override
public void run() {
for (int i=0; i<10; i++){
System.out.println(message);
try {
System.out.println("休眠一下");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

运行:
new Thread(new MyRunable("word")).start();

线程的互斥

多线程中的各个线程都是自由运行的,所以他们有时就会同时操作同一个实例,从而引发逻辑混乱

数据竞争: 线程之间互相竞争引起的与预期相反的情况称为数据竞争或竞态条件
互斥: 管制线程之间的运行,防止发生数据竞争,这种操作称为互斥

synchronized: 用来执行线程的互斥处理。线程的互斥机制称为监视(monitor).另外,获取锁有时也作”拥有监视”或”持有锁”.当前线程是否已获取某一对象的锁可以通过Thread.holdsLock(obj)方法来确认

synchronize的作用域

  • 类级别

    • 1
      2
      3
      4
      5
      class Test{
      public void synchronized(B.class) test(){

      }
      }
    • 1
      2
      3
      4
      5
      class Test{
      public static void synchronized test(){

      }
      }
  • 对象级别

    • class Test{
         public void synchronized(this) test(){
      
          }
      }
      
    • Test1 lock = new Test1()
      class Test{
         public void synchronized(lock) test(){
      
          }
      }
      

线程的协作