赞
踩
进程进一步细化为线程, 是程序内部的一条执行路径. 一个进程中至少有一个线程. 每个线程之间都可以按照顺讯执行自己的代码. 多个线程之间"同时"执行多份代码.
① “并发编程"成为"刚需”
② 虽然多进程也能实现并发编程, 但是线程比进程跟轻量.
③ 线程虽然比进程轻量, 但是人们还不满足, 于是又有了"线程池(ThreadPool)" 和 “协程(Coroutine)”.
线程是操作系统中的概念. 操作系统内核实现了线程这样的机制, 并且对用户层提供了一些 API 供用户使用.
Java中的线程是对系统级别的线程的封装和抽象.
操作系统级别下, 同一个进程的线程之间共享同一个内存空间;
而Java中的线程有私有空间.
创建一个线程类, 继承自Thread类
重写run方法: 线程入口方法, 描述线程执行的动作.
class MyThread extends Thread {
@Override
public void run() {
System.out.println("这里是线程运行的代码");
}
}
创建MyThread类的实例
MyThread t = new MyThread();
调用 start 方法启动线程
t.start(); // 线程开始运行
代码解析:
class MyThread extends Thread {
@Override
public void run() {
while (true) {
System.out.println("MyThread");
}
}
}
public class Main {
MyThread t = new MyThread();
t.start();
while (true) {
System.out.println("Main");
}
}
第十行
t.start()
创建出了新的线程, 执行run()
中的代码.原来的主线程继续往下执行
主线程和新线程是并发执行的关系, 根据操作系统的调度执行.
注意:
IllegalThreadStateException
"实现Runnable接口
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("这里是线程运行的代码");
}
}
创建Thread类的实例, 调用Thread的构造方法将Runnable对象作为参数
Thread t = new Thread(new MyRunnable());
调用start方法
t.start();
通过实现Runnable接口, 使得该类有了多线程的特征. 所有的分线程要执行的代码都在run方法里面.
在启动多线程的时候, 需要先通过Thread类的构造方法Thread(Runnable target)
构造出对象, 然后调用Thread对象的start方法来运行多线程代码.
实际上, 所有的多线程代码都是通过运行Thread.start()
来运行的, 因此, 不管是继承Thread类还是实现Runnable接口来实现多线程, 最终还是通过Thread的对象的API来控制流程的.
说明: Runnable对象仅仅作为Thread对象的target, Runnable实现类里包含的run()方法仅作为线程执行体. 而实际的线程对象依然是Thread实例, 只是该Thread线程负责执行其target的run()方法.
这一方法, 将线程要执行的任务和线程本身, 进一步解耦合了.
联系:
Thread类实际上也是实现了Runnable接口的类
public class Thread extends Object implements Runnable
区别:
实现Runnable接口比继承Thread类所具有的优势
匿名内部类创建Thread子类的对象.
public class Demo3{
Thread t1 = new Thread() {
@Override
public void run() {
System.out.println("使用匿名类创建 Thread 子类对象");
}
};
t1.start();
}
说明:
①
new Thread()
: 创建一个子类, 继承自Thread, 这个子类是匿名的, 并且是在Demo3这个类的内部创建的.② 在子类中重写了run方法
③ 创建了该子类的实例, 并且使用t1这个引用来指向.
匿名内部类创建Runnable子类的对象
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("使用匿名类创建 Runnable 子类对象");
}
});
说明:
①
new Runnable()
: 创建一个类, 实现Runnable接口.② 在类中重写了run方法
③ 创建了该类的实例, 并把这个实例作为参数传给了Thread的构造方法.
lambda表达式创建Runnable子类对象
Thread t3 = new Thread(() -> System.out.println("使用匿名类创建 Thread 子类对象"));
Thread t4 = new Thread(() -> {
System.out.println("使用匿名类创建 Thread 子类对象");
});
基于Callable
Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
//
return null;
}
};
FutureTask<Integer> futureTask = new FutureTask<>(callable);
Thread thread = new Thread(futureTask);
thread.start();
Integer result = futureTask.get();
基于线程池
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(4);
service.submit(new Runnable() {
@Override
public void run() {
//
}
});
}
ExecutorService
: 线程池对象
Executors.newFixedThreadPool(int nThreads)
: 创建固定线程数量的线程池
Executors
: 工厂类newFixedThreadPool(int nThreads)
: 工厂类方法 创建固定线程数量的线程池newCachedThreadPool()
: 创建线程数量动态变化的线程池newSingleThreadExecutor()
: 创建单个线程的线程池newScheduledThreadPool(int corePoolSize)
: 周期性线程池, 类似于定时器的效果ThreadPoolExecutor
的封装, ThreadPoolExecutor
提供了更多的可选参数, 可以进一步细化线程池行为的设定.service.submit(Runnable task)
: 向线程池中添加任务.
找到当前项目使用的jdk的位置, 并双击打开
双击bin目录, 找到jconsole.exe
双击jconsole.exe
, 会出现以下窗口
选择本地进程, 并找到当前运行的
线程名称, 再点击连接
若出现以下窗口, 选择不安全连接.
出现以下窗口后, 点击线程
左下角就列出了所有的线程, 不仅有主线程和自己创建的线程, 还有JVM自带的线程.
点击某个线程, 就能得到该线程的具体信息
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。