09_多线程

多线程

程序是指令和数据的有序集合,其本身没有运行的含义,是一个静态的概念。

进程则是执行程序得一次执行过程,是一个动态的概念。

通常一个进程中包含若干个线程,一个进程至少有一个线程,否则没有存在的意义。线程是CPU调度和执行得单位。

线程创建

Thread、Runnable、Callable

Thread

自定义线程类继承Thread类

重写run()方法,编写线程执行体

创建线程对象,调用start()方法启动线程

public static void main(String[] args){
   //创建线程对象
   StartThread1 t = StartThread1();
   t.start();
}
public class StartThread1 extends Thread{
   //线程入口点
   @Override
   public void run() {
       //线程体
  }
}

Runnable

定义MyRunnable类实现Runnable接口

实现run()方法,编写线程执行体

创建线程对象,调用start()方法启动线程

public class StartThread2 implements Runnable{
   //线程入口点
   @Override
   public void run() {
       //线程体
  }
}
StartThread2 st = new StartThread2(); //创建实现类对象
Thread thread = new Thread(st);  //创建代理类对象
thread.start();  //启动

推荐使用Runnable接口,避免继承局限性,灵活方便

Callable(了解即可)

  1. 实现Callable接口,需要返回值类型

  2. 重写call方法,需要抛出异常

  3. 创建目标对象

  4. 创建执行服务:ExecutorService ser = Executors.newFixedThreadPool(1);

  5. 提交执行:Future<Boolean> result1 = ser.submit(t1);

  6. 获取结果:boolean r1 = result1.get()

  7. 关闭服务:ser.shutdownNow();

静态代理

真实对象和代理对象实现统一接口

代理对象要代理真实角色

线程方法

setPriority(int newPriority) 更改线程的优先级
static void sleep(long millis) 在指定毫秒数内让当前正在执行的线程休眠
void join() 等待该线程终止
static void yield() 暂停当前正在执行的线程对象,并执行其他线程
void interrupt() 中断线程,不使用该方式
boolean isAlive() 测试线程是否处于活动状态

守护(daemon)线程

线程分为用户线程守护线程

虚拟机必须确保用户线程执行完毕

虚拟机不用等待守护线程执行完毕

同步块

synchronized(Obj){ }

Obj称之为同步监视器

死锁

多个线程互相抱着对方需要的资源,形成僵持.

产生死锁的四个必要条件:

  1. 互斥条件:一个资源每次只能被一个进程使用。

  2. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

  3. 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。

  4. 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

Lock(锁)

class A{
   private final ReentrantLock lock = new ReenTrantLock();
   public void m(){
       lock.lock();
       try{
           //保证线程安全的代码;
      }
       finally{
           lock.unlock();
      }
  }
}

线程池

背景:经常创建和销毁、使用量特别大的资源,比如并发情况下的线程,对性能影响很大。

思路:提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中。可以避免频繁创建销毁、实现重复利用。类似生活中的公共交通工具。

好处:

  1. 提高响应速度(减少了创建新线程的时间)

  2. 降低资源消耗(重复利用线程池中线程,不需要每次都创建)

  3. 便于线程管理



上一篇:剑指 Offer 09. 用两个栈实现队列


下一篇:09运算符重载