- 显式继承Thread类。
public class ThreadDemo1 {
//创建线程的方法1:显式继承Thread类
static class MyThread extends Thread {
@Override
public void run() {
System.out.println("hello world,我是一个线程");
while(true) {
//为了不让进程太快结束,使用JDK中内置的jconsole程序来查看线程信息。
}
}
}
public static void main(String[] args) {
//创建线程需要使用Thread类,来创建一个Thread的实例.
//另一方面还需要给这个线程指定,要执行哪些指令/代码。
//指定指令的方式很多,此处先用一个简单的,直接继承Thread类
//重写Thread类中的run方法。
//当Thread对象被创建出来时,内核中并没有随之产生一个线程(PCB)
Thread t = new MyThread();
//执行这个start方法,才是真的创建出了一个线程
//此时内核中才随之出现了一个PCB,这个PCB就会对应让cpu来执行该线程的代码。(上面的run)
t.start();
while(true) {
//为了不让进程太快结束,才能使用JDK中内置的jconsole程序来查看线程信息。
}
}
//这段代码中涉及到两个线程,MyThread创建出的线程和main方法对应的主线程。
}
为了不让进程太快结束,使用JDK中内置的jconsole程序来查看线程信息。
先找到JDK路径,打开bin目录下的jconsole这个JDK内置的程序。
- 匿名内部类的方式继承Thread类。
// 分别用多线程并发执行和单线程来对一个整数进行大量的循环相加
public class ThreadDemo2 {
private static long count = 100_0000_0000L;
public static void main(String[] args) {
//seriol();//串行执行
concurrency();//并发执行
}
private static void seriol() {
long beg = System.currentTimeMillis();//开始的时间戳
int a = 0;
for (long i = 0; i < count;i++) {
a++;
}
int b = 0;
for (long i = 0; i < count;i++) {
b++;
}
long end = System.currentTimeMillis();//结束的时间戳
System.out.println("time: " + (end - beg) + "ms");
}
private static void concurrency() {
long beg = System.currentTimeMillis();//开始的时间戳
//创建线程的方法2:匿名内部类的方式继承Thread类
//匿名内部类,创建了一个没有名字的类,只知道这个类继承自Thread
Thread t1 = new Thread() {
//线程一
@Override
public void run() {
int a = 0;
for (long i = 0; i < count;i++) {
a++;
}
}
};
Thread t2 = new Thread() {
//线程二
@Override
public void run() {
int b = 0;
for (long i = 0; i < count;i++) {
b++;
}
}
};
t1.start();
t2.start();
try {
//线程等待,让主线程等待t1和t2执行结束,然后再继续往下执行
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();//结束的时间戳
System.out.println("time: " + (end - beg) + "ms");
}
}
- 显式创建一个类,实现Runnable接口,然后把这个Runnable的实例关联到Thread实例上。
public class ThreadDemo3 {
//Runnable本质上就是描述了一段要执行的任务代码是啥
static class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("新线程");
}
}
public static void main(String[] args) {
//创建线程的方法3:显式创建一个类,实现Runnable接口,然后把这个Runnable的实例关联到Thread实例上
Thread t = new Thread(new MyRunnable());
t.start();
}
}
- 通过匿名内部类实现Runnable接口。
//创建线程的方法4:通过匿名内部类实现Runnable接口
public class ThreadDemo4 {
public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("新线程");
}
};
Thread t = new Thread(runnable);
t.start();
}
}
- 使用Lambda表达式来指定线程执行的内容。
//创建线程的方法5:使用Lambda表达式来指定线程执行的内容
public class ThreadDemo5 {
public static void main(String[] args) {
Thread t = new Thread(() -> {
System.out.println("新线程");
});
t.start();
}
}
- 上面五种方法执行起来没有本质区别。不过从耦合性来看,方法四和五与其他相比,代码耦合性低,run中没有涉及到任何的Thread内容,意味着容易把这个逻辑从多线程中剥离出来,去搭配其他的并发编程的方式来执行,当然,也容易改为不并发的方式执行。