并发编程
3.Java线程
本章内容
-
创建和运行线程
-
查看线程
-
线程 API
-
线程状态
3.1 创建和运行线程
方法一,直接使用 Thread
// 创建线程对象
Thread t = new Thread() {
public void run() {
// 要执行的任务
}
};
// 启动线程
t.start();
例如:
// 构造方法的参数是给线程指定名字,推荐
Thread t1 = new Thread("t1") {
@Override
// run 方法内实现了要执行的任务
public void run() {
log.debug("hello");
}
};
t1.start();
输出:
19:19:00 [t1] c.ThreadStarter - hello
方法二,使用 Runnable 配合 Thread
把【线程】和【任务】(要执行的代码)分开
-
Thread 代表线程
-
Runnable 可运行的任务(线程要执行的代码)
Runnable runnable = new Runnable() {
public void run(){
// 要执行的任务
}
};
// 创建线程对象
Thread t = new Thread( runnable );
// 启动线程
t.start();
例如:
// 创建任务对象
Runnable task2 = new Runnable() {
@Override
public void run() {
log.debug("hello");
}
};
// 参数1 是任务对象; 参数2 是线程名字,推荐
Thread t2 = new Thread(task2, "t2");
t2.start();
输出:
19:19:00 [t2] c.ThreadStarter - hello
Java 8 以后可以使用 lambda 精简代码
// 创建任务对象
Runnable task2 = () -> log.debug("hello");
// 参数1 是任务对象; 参数2 是线程名字,推荐
Thread t2 = new Thread(task2, "t2");
t2.start();
@FunctionalInterface
Alt+Enter : IDEA中自动简化快捷键
对比:
原理之Thread与Runnable的关系
分析 Thread 的源码,理清它与 Runnable 的关系
小结
-
方法1 是把线程和任务合并在了一起,方法2 是把线程和任务分开了
-
用 Runnable 更容易与线程池等高级 API 配合
-
用 Runnable 让任务类脱离了 Thread 继承体系,更灵活
-
组合大于继承
方法三,FutureTask配合Thread
FutureTask 能够接收 Callable 类型的参数,用来处理有返回结果的情况
// 创建任务对象
FutureTask<Integer> task3 = new FutureTask<>(() -> {
log.debug("hello");
return 100;
});
// 参数1 是任务对象; 参数2 是线程名字,推荐
new Thread(task3, "t3").start();
// 主线程阻塞,同步等待 task 执行完毕的结果
Integer result = task3.get();
log.debug("结果是:{}", result);
输出:
19:22:27 [t3] c.ThreadStarter - hello
19:22:27 [main] c.ThreadStarter - 结果是:100
3.2 观察多个线程同时运行
主要是理解
交替执行
谁先谁后,不由我们控制,任务调度器控制
单核不建议
3.3 查看进程线程的方法
windows
- 任务管理器可以查看进程和线程数,也可以用来杀死进程
- tasklist 查看进程
- taskkill 杀死进程
taskkill /F /PID 28060
linux
-
ps -fe 查看所有进程
-
ps -fT -p 查看某个 进程(PID)的所有线程
-
kill 杀死进程
-
top 按大写 H 切换是否显示线程
-
top -H -p 查看某个进程(PID)的所有线程
Java
- jps 命令查看所有 Java 进程
- jstack 查看某个 Java 进程(PID)的所有线程状态
Jconsole 来查看某个 Java 进程中线程的运行情况(图形界面)
Jconsole 远程监控配置
- 需要以如下方式运行你的 java 类
java -Djava.rmi.server.hostname=`ip地址` -Dcom.sun.management.jmxremote -
Dcom.sun.management.jmxremote.port=`连接端口` -Dcom.sun.management.jmxremote.ssl=是否安全连接 -
Dcom.sun.management.jmxremote.authenticate=是否认证 java类
- 修改 /etc/hosts 文件将 127.0.0.1 映射至主机名
如果要认证访问,还需要做如下步骤
-
复制 jmxremote.password 文件
-
修改 jmxremote.password 和 jmxremote.access 文件的权限为 600 即文件所有者可读写
-
连接时填入 controlRole(用户名),R&D(密码)