一.继承Thread类
1.代码
package org.example;
public class day19 {
//main方法由默认的主线程负责执行
public static void main(String[] args) {
//创建MyThread线程类的对象代表一个线程
final MyThread myThread = new MyThread();
myThread.start(); //启动线程,自动执行run方法
for (int i = 0; i < 5; i++) {
System.out.println("主线程启动:"+i);
}
}
}
package org.example;
public class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("子线程启动输出:"+i);
}
}
}
2.结果
3.总结
优点:编码简单
缺点:线程类已经继承Thread,无法继承其他类,不利于功能的扩展。启动线程必须是调用start方法,不是调用run方法。
不要把主线程任务放在启动子线程之前。
二.实现Runnable接口
1.代码
package org.example;
public class day01 {
public static void main(String[] args) {
//创建任务对象
final MyRunnable myRunnable = new MyRunnable();
//把任务对象交给一个线程对象处理
new Thread(myRunnable).start();
for (int i = 0; i < 5; i++) {
System.out.println("主线程输出:"+i);
}
}
}
package org.example;
public class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("子线程输出:"+i);
}
}
}
2.结果
3.Runnable改为匿名内部类
package org.example;
public class day2 {
public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("子线程输出:"+i);
}
}
};
new Thread(runnable).start();
for (int i = 0; i < 5; i++) {
System.out.println("主线程输出:"+i);
}
}
}
简化一下
package org.example;
public class day2 {
public static void main(String[] args) {
new Thread(()->{
for (int i = 0; i < 5; i++) {
System.out.println("子线程输出:"+i);
}
}).start();
for (int i = 0; i < 5; i++) {
System.out.println("主线程输出:"+i);
}
}
}
4.总结
优点:任务类只是实现接口,可以继续继承其他类、实现其他接口,扩展性强。
缺点:需要多一个Runnable对象。
三.实现Callable接口
1.代码
package org.example;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class day03 {
public static void main(String[] args) throws Exception {
//创建Callable对象
final MyCallable myCallable = new MyCallable(100);
//把Callable对象封装成一个FutureTask任务对象(实现了Runnable对象)
final FutureTask<String> f = new FutureTask<>(myCallable);
//把任务对象交给Thread对象
new Thread(f).start();
//获取执行完毕的结果,如果上面线程未执行完毕,下面这代码会暂停,等待上面执行完
final String s = f.get();
System.out.println(s);
}
}
package org.example;
import java.util.concurrent.Callable;
public class MyCallable implements Callable<String> {
private int n;
public MyCallable(int n){
this.n = n;
}
@Override
public String call() throws Exception {
int sum = 0;
for (int i = 0; i <=n; i++) {
sum += i;
}
return "线程求出的和:"+sum;
}
}
2.结果
3.总结
优点:线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强;可以在线程执行完毕后去获取线程执行的结果。
缺点:编码复杂一点。
四.常用方法
1.获取线程名字
1.代码
package org.example;
public class Thread1 {
public static void main(String[] args) {
final MyThread myThread1 = new MyThread();
myThread1.start();
System.out.println("子线程:"+myThread1.getName());
//主线程对象的名字
final Thread thread = Thread.currentThread();
System.out.println("主线程:"+thread.getName());
for (int i = 0; i < 3; i++) {
System.out.println(thread.getName()+"输出:"+i);
}
}
}
package org.example;
public class MyThread extends Thread{
public void run(){
//获取当前线程
final Thread t = Thread.currentThread();
for (int i = 0; i < 3; i++) {
System.out.println(t.getName()+"输出:"+i);
}
}
}
2.结果
2.设置线程名字
1.代码
package org.example;
public class Thread1 {
public static void main(String[] args) {
final MyThread myThread1 = new MyThread();
myThread1.setName("小王");
myThread1.start();
System.out.println("子线程:"+myThread1.getName());
//主线程对象的名字
final Thread thread = Thread.currentThread();
thread.setName("小子");
System.out.println("主线程:"+thread.getName());
for (int i = 0; i < 3; i++) {
System.out.println(thread.getName()+"输出:"+i);
}
}
}
2.结果
3.设置线程名字方法二
1.代码
package org.example;
public class Thread1 {
public static void main(String[] args) {
final MyThread myThread1 = new MyThread("线程1号");
myThread1.start();
System.out.println("子线程:"+myThread1.getName());
//主线程对象的名字
final Thread thread = Thread.currentThread();
thread.setName("主线程");
System.out.println("主线程:"+thread.getName());
for (int i = 0; i < 3; i++) {
System.out.println(thread.getName()+"输出:"+i);
}
}
}
package org.example;
public class MyThread extends Thread{
public MyThread(String name){
super(name);
}
public void run(){
//获取当前线程
final Thread t = Thread.currentThread();
for (int i = 0; i < 3; i++) {
System.out.println(t.getName()+"输出:"+i);
}
}
}
2.结果
4.sleep线程休眠
1.代码
package org.example;
public class Thread2 {
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 5; i++) {
System.out.println(i);
if(i ==3){
//当i==3时线程休眠5秒再执行后面的
Thread.sleep(5000);
}
}
}
}
5.join
1.代码
package org.example;
public class Thread2 {
public static void main(String[] args) throws InterruptedException {
final MyThread t1 = new MyThread("1号线程");
//join方法,让当前调用这个方法的线程先执行完
t1.start();
t1.join();
final MyThread t2 = new MyThread("2号线程");
t2.start();
t2.join();
}
}
package org.example;
public class MyThread extends Thread{
public MyThread(String name){
super(name);
}
public void run(){
//获取当前线程
final Thread t = Thread.currentThread();
for (int i = 0; i < 3; i++) {
System.out.println(t.getName()+"输出:"+i);
}
}
}
2.结果
sleep
方法是让当前线程暂停执行一段时间,不会影响其他线程的执行;而join
方法是让当前线程等待其他线程结束,会影响其他线程的执行。sleep
方法是静态方法,作用于当前线程;而join
方法是实例方法,作用于其他线程。sleep
方法在时间到达后自动恢复执行,不需要其他线程的参与;而join
方法需要等待指定的线程对象结束才能继续执行。