什么是线程?
过程想要执行工作就须要依赖线程。换句话说,就是过程中的最小执行单位就是线程,并且一个过程中至多有一个线程。
什么是多线程?
指在同一个过程中同时运行多个线程,如你开启 QQ 聊天,能够开启多个窗口。
提到多线程这里要说两个概念,就是串行和并行。
串行:其实是绝对于单条线程来执行多个工作来说的,当咱们下载多个文件时,在串行中它是依照肯定的程序去进行下载的,串行在工夫上是不可能产生重叠的。
并行:下载多个文件,开启多条线程,多个文件同时进行下载,这里是严格意义上的,在同一时刻产生的,并行在工夫上是重叠的。
多线程有三大个性:
原子性:一个操作或者多个操作,要么全副执行胜利,要么全都不执行。
可见性:当多个线程拜访同一个变量时,如果一个线程批改了这个变量的值,其余线程可能立刻看失去批改后的值。
有序性:程序执行的程序依照代码的先后顺序执行。
什么是并发编程?
所谓并发编程是指在一台处理器上“同时”解决多个工作。并发是在同一实体上的多个事件。多个事件在同一时间距离产生。
并发编程的目标:
- 让程序充分利用非计算机资源·
- 放慢程序响应速度(耗时工作、web 服务器)
- 简化异步工夫的解决。
实现多线程的形式:
1) 继承 Thread
Thread 类实质上是实现了 Runnable 接口的一个实例,代 表一个线程的实例。启动线程的惟一办法就是通过 Thread 类的 start()实例办法。
public class MyThread extends Thread {public void run() {System.out.println("MyThread.run()");
}
}
MyThread myThread1 = new MyThread();
MyThread myThread2 = new MyThread();
myThread1.start();
myThread2.start();
2) 实现 Runnable 接口
如果本人的类曾经 extends 另一个类,就无奈间接 extends Thread,此时,能够实现一个 Runnable 接口
public class MyThread extends OtherClass implements Runnable {public void run() {System.out.println("MyThread.run()");
}
}
3)实现 Callable 接口通过 FutureTask 包装器来创立 Thread 线程
public class CallableDemo implements Callable<String> {public static void main(String[] args) throws ExecutionException, InterruptedException {ExecutorService executorService = Executors.newFixedThreadPool(1);
CallableDemo callableDemo = new CallableDemo();
Future<String> future = executorService.submit(callableDemo);
System.out.println(future.get());
executorService.shutdown();}
@Override
public String call() throws Exception {
int a = 1;
int b = 2;
System.out.println(a + b);
return "执行后果:" + (a + b);
}
}
线程的状态:
创立完的线程具备生命周期,从创立到死亡,两头还有一些其余状态的变动。
1)新建状态(New) : 线程对象被创立后,就进入了新建状态。例如,Thread thread = new Thread()。
2)就绪状态 (Runnable): 也被称为“可执行状态”。线程对象被创立后,其它线程调用了该对象的 start() 办法,从而来启动该线程。例如,thread.start()。处于就绪状态的线程,随时可能被 CPU 调度执行。
3)运行状态(Running) : 线程获取 CPU 资源后进行执行。须要留神的是,线程只能从就绪状态进入到运行状态。
4)阻塞状态(Blocked) : 阻塞状态是线程因为某种原因让出 CPU 资源,临时进行运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的状况分三种:
期待阻塞 – 通过调用线程的 wait()办法,让线程期待某工作的实现。同步阻塞 – 线程在获取 synchronized 同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态。其余阻塞 – 通过调用线程的 sleep()或 join()或收回了 I / O 申请时,线程会进入到阻塞状态。当 sleep()状态超时、join()期待线程终止或者超时、或者 I / O 处理完毕时,线程从新转入就绪状态。
5)死亡状态 (Dead) : 线程顺利执行完了或者因异样退出了 run() 办法,该线程完结生命周期。
线程的罕用办法:
编号 | 办法 | 阐明 |
---|---|---|
1 | public void start() |
使该线程开始执行;Java 虚拟机调用该线程的 run 办法。 |
2 | public void run() |
如果该线程是应用独立的 Runnable 运行对象结构的,则调用该 Runnable 对象的 run 办法;否则,该办法不执行任何操作并返回。 |
3 | public final void setName(String name) |
扭转线程名称,使之与参数 name 雷同。 |
4 | public final void setPriority(int priority) |
更改线程的优先级。 |
5 | public final void setDaemon(boolean on) |
将该线程标记为守护线程或用户线程。 |
6 | public final void join(long millisec) |
期待该线程终止的工夫最长为 millis 毫秒。 |
7 | public void interrupt() |
中断线程。 |
8 | public final boolean isAlive() |
测试线程是否处于活动状态。 |
9 | public static void yield() |
暂停以后正在执行的线程对象,并执行其余线程。 |
10 | public static void sleep(long millisec) |
在指定的毫秒数内让以后正在执行的线程休眠(暂停执行),此操作受到零碎计时器和调度程序精度和准确性的影响。 |
11 | public static Thread currentThread() |
返回对以后正在执行的线程对象的援用。 |
进行线程:
进行线程是在多线程开发时很重要的技术点,把握此技术能够对线程的进行进行无效的解决。
在 Java 中有以下 3 种办法能够终止正在运行的线程:
- 应用退出标记,使线程失常退出,也就是当 run 办法实现后线程终止
- 应用 stop 办法强行终止线程,然而不举荐应用这个办法,因为 stop 和 suspend 及 resume 一样,都是作废过期的办法,应用他们可能产生不可意料的后果。
- 应用 interrupt 办法中断线程,但这个不会终止一个正在运行的线程,还须要退出一个判断才能够实现线程的进行。
多线程留神点:
多线程编程给咱们带来了很多的劣势,如充分利用处理器资源,并行做多件事件,然而在开发多线程利用时,咱们须要留神的问题有很多,比方线程同步、线程死锁等等。
- 线程平安
在单线程环境下,不加锁也没有线程平安和不平安问题,但多线程拜访时,须要线程同步拜访来保障线程平安,如同时有两个线程,线程 A 和线程 B, 对同一个账号金额进行批改操作,当采纳了加锁机制时,A 线程在批改账号金额,B 线程不能进行拜访,直到 A 线程读取完,B 线程才可应用,这样就不会呈现数据不统一或者数据净化。 - 线程死锁
线程死锁是指多个线程竞争同一个资源,各自阻塞期待其余线程持有的锁,例如:
1. 线程 1 锁住了 A 资源,而后尝试去对 B 资源加锁,同时线程 2 曾经锁住了 B 资源,再尝试对 A 加锁,为了彼此都能失去所需的资源而互相阻塞期待,从而产生了死锁。
更多 java 根底材料等你来拿!!!