为什么要使用多线程快速到底
现在开始使用电脑,打开 QQ,打开浏览器,打开腾讯课堂。如果我使用单线程,那么要想三个功能一起使用,那几乎不可能,因为一个线程开始执行 QQ,没执行两秒钟又去执行浏览器,然后还要执行腾讯课堂,那么这三个是不肯能做到同时播放的。多线程就是用来解决此问题,如果有 n 个线程,每个任务都有自己的线程在执行,那么就可以实现同时播放了。
创建线程的方式
创建线程有两种方式:
1、继承 Thread,重写父类的 run() 方法。
package com.thread;
public class MyThread extends Thread
{
@Override
public void run()
{
for (int i = 0; i < 5; i++)
{
System.out.println(Thread.currentThread().getName()+"在运行!");
}
}
public static void main(String[] args)
{
MyThread myThread = new MyThread();
myThread.start();
for (int i = 0; i < 5; i++)
{
System.out.println(Thread.currentThread().getName()+"在运行");
}
}
}
运行结果
main在运行
main在运行
main在运行
Thread-0在运行!
main在运行
Thread-0在运行!
Thread-0在运行!
Thread-0在运行!
Thread-0在运行!
main在运行
看到 main 线程和 Thread-0 线程交替运行,效果明显
所谓的多线程,指的是两个线程的代码可以同时运行,而不必一个线程需要等待另一个线程内的代码执行完才可以运行。对于单核CPU来说,是无法做到真正的多线程的,因为每个时间点上,CPU 都会执行特定的代码,由于 CPU 执行代码时间很快,所以两个线程的代码交替执行看起来像是同时执行的一样(相反对于多核 CPU 是可以真正的做到同时执行的)。那具体执行某段代码多少时间,就和分时机制系统有关了。分时系统把 CPU 时间划分为多个时间片,操作系统以时间片为单位分配给各个线程,越好的 CPU 执行的速度越快,有可能在一个时间片内就把这个线程所有要执行的的任务都执行完了。所以看不到明显效果也很正常。所以,要想看出交替的效果就是把 for 循环的值调大一点就可以了(也可以在 for 循环里加Thread.sleep 方法)。
2、实现 Runnable 接口,实现 Runnable 接口中的 run() 方法
package com.thread;
public class MyThread implements Runnable
{
@Override
public void run()
{
for (int i = 0; i < 5; i++)
{
System.out.println(Thread.currentThread().getName()+"在运行");
}
}
public static void main(String[] args)
{
MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();
for (int i = 0; i < 5; i++)
{
System.out.println(Thread.currentThread().getName()+"在运行");
}
}
}
运行结果
main在运行
Thread-0在运行
Thread-0在运行
Thread-0在运行
Thread-0在运行
Thread-0在运行
main在运行
main在运行
main在运行
main在运行
两种方式
Thread 类
public class Thread implements Runnable {}
Runnable 接口
public interface Runnable {
public abstract void run();
}
其实 Thread 类也是实现的Runnable接口。两种实现方式对比的关键就在于 extends 和 implements 的对比,当然是后者好。因为第一,继承只能单继承,实现可以多实现;第二,实现的方式对比继承的方式,也有利于减小程序之间的耦合。因此,多线程的实现几乎都是使用的 Runnable 接口的方式。
线程状态
虚拟机中的线程状态有六种,定义在Thread.State(是一个枚举类型)中:
1、新建状态 NEW
/**
* Thread state for a thread which has not yet started.
*/
NEW,
new了但是没有启动的线程的状态。比如 " Thread t = new Thread() " ,t 就是一个处于 NEW 状态的线程
2、可运行状态 RUNNABLE
/**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
RUNNABLE,
new出来线程,调用 start() 方法即处于 RUNNABLE 状态了。处于 RUNNABLE 状态的线程可能正在 Java 虚拟机中运行,也可能正在等待处理器的资源,因为一个线程必须获得 CPU 的资源后,才可以运行其 run() 方法中的内容,否则排队等待
3、阻塞BLOCKED
/**
* Thread state for a thread blocked waiting for a monitor lock. 也就是说:阻塞就是该线程在等待监视器锁,以便进入一个同步的方法
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
*/
BLOCKED,
如果某一线程正在等待监视器锁,以便进入一个同步的块/方法,那么这个线程的状态就是阻塞BLOCKED
4、等待 WAITING
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called <tt>Object.wait()</tt>
* on an object is waiting for another thread to call
* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
* that object. A thread that has called <tt>Thread.join()</tt>
* is waiting for a specified thread to terminate.
*/
某一线程因为调用不带超时的 Object 的 wait() 方法、不带超时的 Thread 的 join() 方法、LockSupport 的 park() 方法,就会处于等待 WAITING 状态
5、超时等待 TIMED_WAITING
/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
某一线程因为调用带有指定正等待时间的 Object 的 wait() 方法、Thread 的 join() 方法、Thread 的 sleep() 方法、LockSupport 的 parkNanos() 方法、LockSupport 的 parkUntil() 方法,就会处于超时等待 TIMED_WAITING 状态
6、终止状态 TERMINATED
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
线程调用终止或者 run() 方法执行结束后,线程即处于终止状态。处于终止状态的线程不具备继续运行的能力