当前位置: 首页 > 图灵资讯 > 技术篇> JAVA_线程

JAVA_线程

来源:图灵教育
时间:2023-06-09 10:19:04

一、概念

一个程序至少需要一个过程,而一个过程至少需要一个线程。

关系:线程–>进程–>程序。

因此,线程是程序执行流的最小单位,过程是系统资源分配和调度的独立单位。

二、线程实现方式1.继承Thread类

1)定义Thread类子类,重写这种run方法;

2)创建Thread子类的例子,即创建线程对象

3)调用线程对象的start()方法启动线程;

public class MYThread extends Thread{

@Override

public void run() {

super.run();

}

}

2.实现Runnable接口

1)定义runnable接口的实现类,并重写run()接口的方法;

2)创建 Runnable实现实例,并以此实例为threadtarget创建thread对象,thread对象是真正的线程对象;

3)调用线程对象的start()方法启动线程;

new Thread(new Runnable() { ---对象

public void run() { -- run() 方法

}

}).start(); --调用

 

3.通过Callable和Future创建线程

1)创建callable接口的实现类,实现call()方法,call()方法将作为线程执行体,并具有返回值;

2)创建Callable实现类实例,使用Futuretask类包装Callable对象,Futuretask对象包装Callable对象的calll()方法返回值;

3)以futuretask对象为thread对象的target创建并启动新线程;

4)调用futuretask对象的get()方法获得子线程执行后的返回值。

比较三种方式:

1. 采用实现 Runnable、Callable 当接口创建多线程时,线程类只是实现了 Runnable 接口或 Callable 接口,也可以继承其他类别;这样,多个线程可以共享相同的target对象;

缺点:编程比较复杂,如果要访问当前线程,必须使用Thread.currentThread()方法;

2. 使用继承 Thread 创建多线程时,编写简单。如果需要访问当前线程,则无需使用 Thread.currentThread() 方法,直接使用 this 即可获得当前线程;

缺点:线程类已经继承了Thread类,因此不能继承其他父类。

三、线程状态

1.新建状态(New):new初始化,线程对象新建;

2.就绪状态(Runnable):线程对象创建后,其他线程调用对象的start()方法;

3.运行状态(Running):线程获得CPU执行权限。需要注意的是,线程只能从就绪状态进入运行状态;

4.阻塞状态(Blocked):在获得synchronized排他锁失败(因为锁被其他线程占用)时,线程会进入同步阻塞状态;

5.等待(Waiting):进入这种状态的线程需要等待其他线程做出一些特定的动作线程显式唤醒(通知或中断);

6.死亡状态(Dead):线程执行或因异常退出run()方法,线程结束生命周期;

四、常用的线程方法
  1. Thread.currentThead():获取当前线程对象;
  2. getPriority():获取当前线程的优先级;
  3. setPriority():设置当前线程的优先级;

注:线程优先级高,CPU调度的概率高,但不代表一定会运行,而且线程优先级低的概率小。

  1. isAlive():判断线程是否处于活动状态 (线程调用start后,即处于活动状态)
  2. join():强制执行调用join方法的线程,其他线程处于阻塞状态,然后在执行该线程后执行其他线程。

注:InteruptedException有可能被外界中断 中断异常。

  1. sleep():目前正在执行的线程休眠(暂停执行)应在指定的毫秒内进行。休眠线程被阻塞。
  2. yield():调用yield方法的线程会礼让其他线程先运行。(其他线程高概率先运行,小概率自己运行);
  3. interrupt():中断线程;
  4. wait():导致线程等待,进入堵塞状态。该方法仅用于同步方法或同步代码块;
  5. notify():唤醒当前线程并进入运行状态。该方法仅用于同步方法或同步代码块;
  6. notifyAll():唤醒所有等待的线程。该方法仅用于同步方法或同步代码块;
五、多线程安全

线程安全是什么?

如果代码可以在多线程和单线程上执行,总是可以得到相同的结果,那么它是安全的。

1.线程的安全性体现在:

1)原子性:一个或多个操作 CPU 执行过程中不中断的特征

2)可见性:一个线程修改共享变量,另一个线程可以立即看到

3)有序性:程序执行顺序按代码顺序执行

2.原因:

1)缓存引起的可见性问题

2)线程切换引起的原子性问题

3)编译优化带来的有序问题

3.解决方案:

1)JDK Atomic 原子类的开头,synchronized、Lock,能解决原子性问题;

2)synchronized、volatile、Lock,可以解决可见性问题;

3)Happens-Before JVM对程序运行设置的一些规则可以解决有序性问题。