注:使用idea开发
一.java中操作线程的原理
1.操作系统为我们提供了一些API(程序之间的接口),但是不同操作系统API不同,所以java对API进行封装,可实现跨平台编译.
二.具体实现的方法
1.使用Thread类,创造出线程,进一步操作系统的线程.
三.Thread类(基础用法)
1.是什么
JVM⽤来管理线程的⼀个类,换句话说,每个线程都有⼀个唯⼀的Thread对象与之关
联。
2.属性
java标准库的内置的类,在java.lang包中,可直接使用,不需要import(导包)
class MyThread extends Thread {} //创造一个类,继承线程类
3.run(核心)
//每个线程都有一个入口,run方法就是线程的入口 class MyThread extends Thread { public void run(){..} }
当一个程序跑起来,就是一个进程,其中至少有一个主线程,main方法就是其入口方法
4.线程的"定义"
以一段代码为例:
class MyThread extends Thread{ public void run(){ //线程的入口方法 System.out.println("hello Thread"); } }
5.start线程的调用
public static void main(String[] args) {
Thread t = new MyThread();
//start和run都是Thread的成员
//run只是描述了线程的入口,并没调用
//start则是真正的调用系统API,在系统中创建线程,在线程中调用run
t.start();
}
6.start 与 run 的区别
start调用系统 API,在系统内核中创建出线程
run方法单纯描述线程中执行的任务(在start创建好线程之后自动被调用)
本质区别,差别在与系统内部创建出新线程
7.线程并发执行的体现
调用主线程和创建的线程,在二者之中循环打印,观察执行结果,
代码如下:
//继承Thread 一个线程 class MyThread extends Thread{ public void run(){ //线程的入口方法 while (true){ System.out.println("hello Thread"); } } } //创建主线程 public class Demo1 { public static void main(String[] args) { Thread t = new MyThread(); t.start(); while (true){ System.out.println("hello main"); } } }
执行结果如下:
不间断循环打印两个线程中的打印语句
结论:
可以看出,两者并发执行的
6.sleep方法
由于在控制台上输出过快,观察不清晰,使用Thread中sleep方法增加每次打印的时间间隔
当我们修改成这样时,会发现一个异常提示
这个异常为受查异常,必须要显示处理,但此处只能使用try catch而不能使用throws,原因为
此代码是重写父类的run,父类的run没有throws,所以子类也不能有throws,代码如下:
public class Demo1 { public static void main(String[] args) { Thread t = new MyThread(); t.start(); //t.run(); while (true){ System.out.println("hello main"); } } }
Java 语言定义了一些异常类在 java.lang 标准包中。标准运行时异常类的子类是最常见的异常类。由于 java.lang 包是默认加载到所有的 Java 程序的,所以大部分从运行时异常类继承而来的异常都可以直接使用。
接下来我们写main方法中的sleep:二者都可以
public static void main(String[] args) throws InterruptedException { Thread t = new MyThread(); t.start(); //t.run(); while (true){ System.out.println("hello main"); Thread.sleep(1000); } }
public static void main(String[] args) { Thread t = new MyThread(); t.start(); //t.run(); while (true){ System.out.println("hello main"); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } }
四.Thread类创造线程的其他写法
1.继承Thread,重写run
//继承Thread 一个线程
class MyThread extends Thread{
public void run(){
//线程的入口方法
while (true){
System.out.println("hello Thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
//创建主线程
public class Demo1 {
public static void main(String[] args) {
Thread t = new MyThread();
t.start();
//t.run();
while (true){
System.out.println("hello main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
2.实现Runnable(接口),重写run
Runnable表示一个可执行的任务,这个任务可以交给线程运行,或是其他实体运行都可以
这与继承Thread写法最大区别就是?? 解耦合
任务本身和线程联系变小,可使用单线程多线程执行,或是其他方式
class myRunnable implements Runnable{
@Override
public void run() {
while (true){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class Demo2 {
public static void main(String[] args) throws InterruptedException {
Runnable runnable = new myRunnable();
Thread t = new Thread(runnable);
t.start();
while (true){
System.out.println("hello main");
Thread.sleep(1000);
}
}
}
3.使用匿名内部类
1,继承Thread,重写run
public class Demo3 {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(){
@Override
public void run() {
while (true){
System.out.println("hellq thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
};
t.start();
while (true){
System.out.println("hellq main");
Thread.sleep(1000);
}
}
}
2,使用Runnable,重写run,也是使用匿名内部类
public class Demo5 {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while (true){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
});
while (true){
System.out.println("hello main'");
Thread.sleep(1000);
}
}
}
4.基于lambda表达式(推荐)
这是一种更加简化的语法表示方式,"语法糖",相当匿名内部类的替换写法
public class Dome4 {
public static void main(String[] args) {
Thread t = new Thread(()->{
while (true){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
t.start();
while (true){
System.out.println("hello main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
lambda自身就是run方法,本身就是表逻辑,作为线程的入口
五.观察进程中多线线程的情况
1.工具 jconsole
在idea中有一个窗口,可查看线程信息,但是有难度对新手不友好,我们这里使用JDK自带的工具
2.打开-显示情况
我们运行上面的代码之后:打开这个jconsole