多线程的创建与Thread的常用方法

简介: 多线程的创建与Thread的常用方法

1.多线程的创建

Thread类

Java是通过java.lang.Thread类来代表线程的。

按照面向对象的思想,Thread类提供了实现多线程的方式。

1.1方式一:继承Thread类

多线程的实现方案一:继承Thread类

① 定义一个子类MyThread继承线程类java.lang.Thread,重写run()方法。

② 创建MyThread类的对象。

③ 调用线程对象的start()方法启动线程(启动后还是执行run方法的)。

方式一优缺点:

优点:编码简单。

缺点:线程类已经继承Thread,无法继承其他类,不利于扩展。

示例代码如下:

publicclassThreadDemo1 {
publicstaticvoidmain(String[] args) {
// 3.实例化线程对象Threadt=newMyThread();
// 4.调用start方法启动子线程(执行run方法)t.start();
for (inti=0; i<5; i++) {
System.out.println("主线程执行输出:"+i);
        }
    }
}
/*** 1.自定义一个线程类继承Thread类*/classMyThreadextendsThread {
/*** 2.重写run方法,其中是此线程要做的工作*/@Overridepublicvoidrun() {
for (inti=0; i<5; i++) {
System.out.println("子线程执行输出:"+i);
        }
    }
}

注:main方法中不是直接调用run方法,而是调用start方法启动线程中的run方法。

直接调用run方法会当成普通方法执行,此时相当于还是单线程执行。

只有调用start方法才是启动一个新的线程执行。

注意将主线程任务放在子线程任务之后,否则主线程执行完毕后再执行子线程,相当于是一个单线程的效果。

1.2方式二:实现Runnable接口

多线程的实现方案二:实现Runnable接口

① 定义一个线程任务类MyRunnable实现Runnable接口,重写run()方法。

② 创建MyRunnable任务对象。

③ 把MyRunnable任务对象交给Thread处理。

④ 调用线程对象的start()方法启动线程。

Thread类构造器

方法名

说明

public Thread(String name)

可以为当前线程指定名称

public Thread(Runnable target)

封装Runnable对象成为线程对象

public Thread(Runnable target ,String name )

封装Runnable对象成为线程对象,并指定线程名称

 

方式二优缺点:

优点:线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强。

缺点:编程多一层对象包装,如果线程有执行结果是不可以直接返回的。

示例代码如下:

publicclassThreadDemo2 {
publicstaticvoidmain(String[] args) {
// 3.创建一个任务对象Runnabletarget=newMyRunnable();
// 4.把任务对象交给Thread处理Threadt=newThread(target);
// 5.启动线程t.start();
for (inti=0; i<5; i++) {
System.out.println("主线程执行:"+i);
        }
    }
}
/*** 定义一个线程任务类,实现Runnable接口*/classMyRunnableimplementsRunnable {
/*** 重写run方法,定义线程的执行任务*/@Overridepublicvoidrun() {
for (inti=0; i<5; i++) {
System.out.println("子线程执行:"+i);
        }
    }
}

多线程的实现方案二:实现Runnable接口(匿名内部类形式)

① 可以创建Runnable的匿名内部类对象。

② 交给Thread处理。

③ 调用线程对象的start()启动线程。

示例代码如下:

publicclassThreadDemo2Other {
publicstaticvoidmain(String[] args) {
newThread(() -> {
for (inti=0; i<5; i++) {
System.out.println("子线程执行:"+i);
            }
        }).start();
for (inti=0; i<5; i++) {
System.out.println("主线程执行:"+i);
        }
    }
}

1.3方式三:JDK 5.0新增:实现Callable接口

前2种线程创建方式都存在一个问题:他们重写的run方法均不能直接返回结果,不适合需要返回线程执行结果的业务场景。

怎么解决这个问题呢?JDK 5.0提供了Callable和FutureTask来实现,这种方式的优点是可以得到线程执行的结果

多线程的实现方案三:利用Callable、FutureTask接口实现

①得到任务对象

1)定义类实现Callable接口,重写call方法,封装要做的事情。

2)用FutureTask把Callable对象封装成线程任务对象。

②把线程任务对象交给Thread处理。

③调用Thread的start方法启动线程,执行任务

④线程执行完毕后、通过FutureTask的get方法去获取任务执行的结果。

FutureTask的常用API

方法名

说明

public FutureTask<>(Callable call)

把Callable对象封装成FutureTask对象

(需要声明任务对象返回值的泛型)

public V get() throws Exception

获取线程执行call方法返回的结果

 

示例代码如下:

publicclassThreadDemo3 {
publicstaticvoidmain(String[] args) {
// 3.创建Callable任务对象Callable<String>call=newMyCallable(10);
// 4.将Callable任务对象交给FutureTask对象,封装为真正的任务对象/*FutureTask对象的作用:实现了Runnable接口,可以交给Thread对象处理可以在线程执行完毕之后通过调用其get方法获取线程执行完毕的返回值*/FutureTask<String>f=newFutureTask(call);
// 5.将任务对象交给Thread处理Threadt=newThread(f);
// 6.启动线程t.start();
Callable<String>call2=newMyCallable(20);
FutureTask<String>f2=newFutureTask(call2);
Threadt2=newThread(f2);
t2.start();
try {
// 若任务没有执行完毕,则代码会在这里等待,直至线程执行完毕,再执行get方法,获取返回值Stringrs=f.get();
System.out.println("第1个结果:"+rs);
        } catch (Exceptione) {
e.printStackTrace();
        }
try {
Stringrs2=f2.get();
System.out.println("第2个结果:"+rs2);
        } catch (Exceptione) {
e.printStackTrace();
        }
    }
}
/*** 1.定义一个任务类,实现Callable接口,需要声明泛型,表明返回值类型*/classMyCallableimplementsCallable<String> {
privateintn;
publicMyCallable(intn) {
this.n=n;
    }
/*** 2.重写call方法(任务方法)   此处为求和方法** @return* @throws Exception*/@OverridepublicStringcall() throwsException {
intsum=0;
for (inti=1; i<=n; i++) {
sum+=i;
        }
return"子线程执行结果"+sum;
    }
}

注:若任务没有执行完毕,则代码会在获取返回值的get方法处等待,直至线程执行完毕,再执行get方法,获取返回值。

2.Thread的常用方法

Thread类常用方法

方法名

说明

String getName ()

获取当前线程的名称,默认线程名称是Thread-索引

void setName (String name)

将此线程的名称更改为指定的名称,

通过构造器也可以设置线程名称

public static Thread currentThread()

返回对当前正在执行的线程对象的引用

public static void sleep(long time)

让当前线程休眠指定的时间后再继续执行,单位为毫秒

public void run()

线程任务方法

public void start()

线程启动方法

 

示例代码如下:

自定义MyThread类

publicclassMyThreadextendsThread {
publicMyThread() {
    }
publicMyThread(Stringname) {
// 为当前线程对象设置名称,交给父类有参构造器初始化super(name);
    }
@Overridepublicvoidrun() {
for (inti=0; i<5; i++) {
System.out.println(Thread.currentThread().getName() +"输出:"+i);
        }
    }
}
测试类publicclassThreadDemo1 {
publicstaticvoidmain(String[] args) throwsInterruptedException {
Threadt=newMyThread("1号线程");
t.start();
Threadt2=newMyThread("2号线程");
t2.start();
// 哪个线程执行它,它就得到哪个线程对象(当前线程对象)Threadm=Thread.currentThread();
System.out.println(m.getName()); // 主线程名称为"main"for (inti=0; i<5; i++) {
if (i==2) {
// 让线程休眠3sThread.sleep(3000);
            }
System.out.println("main线程输出:"+i);
        }
    }
}

程序运行结果如下:

main

main线程输出:0

main线程输出:1

1号线程输出:0

1号线程输出:1

1号线程输出:2

1号线程输出:3

1号线程输出:4

2号线程输出:0

2号线程输出:1

2号线程输出:2

2号线程输出:3

2号线程输出:4

main线程输出:2

main线程输出:3

main线程输出:4

相关文章
|
4天前
|
监控 测试技术 程序员
解决线程死循环问题的有效方法
作为开发者想必都清楚,多线程应用程序的开发为我们日常开发工作中提供了并发执行任务的能力,但线程死循环问题却是一个常见而令人头疼的挑战,因为线程死循环可能导致系统的不稳定性、资源浪费以及应用程序的异常运行,所以准确地定位和妥善处理线程死循环现象,并在编码阶段就避免潜在风险,成为开发人员必须面对的重要问题,线程死循环问题的解决不仅有助于提高系统的稳定性和可用性,还能优化资源利用和提升应用程序的性能,通过采取适当的预防和处理措施,开发人员能够避免线程陷入无尽的循环,并及时发现和解决潜在问题。那么本文就来分享一下关于如何处理线程死循环问题,以及如何在编码阶段规避潜在风险。
44 2
解决线程死循环问题的有效方法
|
4天前
|
Java 中间件 API
【C/C++ 线程 】深入浅出:理解 std::thread 的局限性
【C/C++ 线程 】深入浅出:理解 std::thread 的局限性
53 2
|
4天前
|
Java 调度 C#
C#学习系列相关之多线程(一)----常用多线程方法总结
C#学习系列相关之多线程(一)----常用多线程方法总结
|
4天前
|
Java 测试技术
血的教训--如何正确使用线程池submit和execute方法
血的教训--如何正确使用线程池submit和execute方法
27 1
|
4天前
|
存储 前端开发 算法
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析(一)
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析
61 0
|
4天前
|
存储 并行计算 Java
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析(二)
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析
74 0
|
4天前
|
安全 Java 调度
Java一分钟:多线程编程初步:Thread类与Runnable接口
【5月更文挑战第11天】本文介绍了Java中创建线程的两种方式:继承Thread类和实现Runnable接口,并讨论了多线程编程中的常见问题,如资源浪费、线程安全、死锁和优先级问题,提出了解决策略。示例展示了线程通信的生产者-消费者模型,强调理解和掌握线程操作对编写高效并发程序的重要性。
45 3
|
4天前
简便的方法开线程干活并且出现等待提示
简便的方法开线程干活并且出现等待提示
14 3
|
4天前
|
Java API 调度
【Java多线程】Thread类的基本用法
【Java多线程】Thread类的基本用法
10 0
|
4天前
|
算法 安全 调度
【C++入门到精通】 线程库 | thread类 C++11 [ C++入门 ]
【C++入门到精通】 线程库 | thread类 C++11 [ C++入门 ]
17 1