Java线程

多线程

一、概念

1、进程和线程的概念

  • 进程和线程都是操作系统中的概念,操作系统对进程和线程的严格定义是:进程是具有一定独立功能的程序,是系统进行资源分配和调度的独立单位。线程是进程的实体,是cpu调度和分配的基本单位。

2、进程与线程的关系

  • 一个线程只能属于一个进程,而一个进程可以有多个线程。
  • 同一进程的所有线程共享该进程的资源。
  • 线程在执行过程中,不同进程的线程间要利用消息通信的办法实现数据同步。

3、线程的生命周期

  • 主要有创建,就绪,运行,阻塞,销毁几个状态,如图:

2、java与多线程

  • java为了提升程序性能,也引入了多线程概念,通过多线程,在一些场景能极大提升性能,实现线程主要有两种方式,一种继承Thread类,另一种实现Runable接口,
    2.1 继承Thread类型
  • 创建线程,可以通过继承Thread类并实现run()方法的形式,run()里面编写实际要运行的代码,运行时通过start()方法将线程设为可运行态,并不是直接执行,具体调用还是要操作系统决定。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    /**
* 继承Thread
*/
public class TestThread extends Thread{

private String threadName;

public TestThread(String name){
this.threadName=name;
}

@Override
public void run(){
System.out.print(threadName);
}
}
2.2 实现Runnable接口
  • 线程类通过实现Runnable接口,实现run()方法,也能实现线程调用,和继承Thread类类似,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
public class RunnableThread implements Runnable{

private String threadName;

public RunnableThread(String name){
this.threadName=name;
}

@Override
public void run(){
System.out.println(threadName);
}
}
2.3 详细的启动过程
  • 1、通过new创建一个线程对象
  • 2、调用线程对象的start()方法,使线程处理Runnable可运行状态,等待调用
  • 3、当被调用时,执行run()中的代码
  • 4、当线程因为原因在运行时放弃cpu调用时(比如被优先级高的线程抢占),便会进入阻塞状态,当要继续运行时,需要重新进入可运行状态。
  • 5、执行完成,会进入销毁状态。

3、线程同步

  • 同一个进程的线程资源是共享的,当操作共享资源时,会存在问题,为了避免临界区造成的问题,线程之间需要进行同步,主要有下面几种同步方式
3.1、使用synchronized进行修饰
  • 在需要同步的方法面前加入synchronized进行修饰,synchronized会将对象锁住,能够保证在同一时刻只有一个线程访问,在调用方法之前,需要先获得内置锁,同时,除了修饰方法,还能修饰代码块
1
public void synchronized saveMoney(){//todo somethind};
1
synchronized(object){}; //修饰对象
3.2、使用Lock锁
  • 锁机制也能保证同一个时刻只能有一个线程进行访问,在在java.util.concurrent.locks包中有很多Lock的实现类,常用的有ReentrantLock可重入锁等
1
2
3
4
5
6
7
     Lock l = ...; //lock实现对象对象
l.lock();
try {
//todo something
} finally {
l.unlock();
}
3.3 volatile
  • volatile主要保证了一个共享变量在多个线程访问的情况下,保证了共享变量的可见性,比如一个线程对变量进行了修改,另一个线程能同步到修改的值。

4、线程池

  • 在单个线程的使用中,频繁的创建销毁线程对象损耗较多的时间,影响系统性能,当有任务来时,临时创建性能也非常低效,节省了时间和效率。所以在多线程的开发中,尽量使用线程池的形式。
4.1、ThreadPoolExecutor
  • 使用ThreadPoolExecutor进行创建线程池,用法
1
2
3
4
5
6
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
}
  • corePoolSize是核心池的大小,maximumPoolSize最大线程数,keepAliveTime当没有任务时线程的存活时间,weekQueue阻塞队列,用来保存执行的任务,unit时间单位
  • 协作流程:线程优先向 CorePool 中提交;在 Corepool 满了之后,线程被提交到任务队列,等待线程池空闲;在任务队列满了之后 corePool 还没有空闲,那么任务将被提交到 maxPool 中,如果 MaxPool 满了之后执行 task 拒绝策略。

热评文章