本篇文章为你整理了多线程(一)(多线程一定要加锁么)的详细内容,包含有多线程一定比单线程快吗 多线程一定要加锁么 多线程一定快吗 多线程一般应用场景 多线程(一),希望能帮助你了解 多线程(一)。
大佬的理解- Java多线程(一)多线程基础
大佬的理解- Java多线程(二)常用的实现多线程的两种方式
1、继承Thread类
继承Thread必须重写run方法,(具体业务执行方法,需要执行的业务方法,定义在此方法中),注意此方法是线程启动后线程自动调用的;
案例
public class MyThread extends Thread{
@Override
public void run() {
//线程执行的业务方法
System.out.println("子线程执行");
for (int i = 0;i i++){
System.out.println("--- 线程名---:"+Thread.currentThread().getName()+",序号:"+i);
public static void main(String[] args) {
//主线程
System.out.println("***主线程执行***");
System.out.println("***线程名***:"+Thread.currentThread().getName());
//创建一个线程并启动,只能通过主线程创建其他线程
MyThread thread1 = new MyThread();
MyThread thread2 = new MyThread();
//启动线程:start()方法(一旦启动,自动启动子线程,当前线程继续向下执行,不会等子线程)
thread1.start();
//启动多线程
//多线程并发执行:不是正真一样上的并行执行(肉眼感官是并行),而是通过cpu的调度算法,有序cpu执行极快,所以肉眼看起来是并行的;
thread2.start();
//调用run方法,不可以启动线程,就是对象的普通方法调用,等run方法执行结束,主线程才能继续执行
//thread1.run();
//thread2.run();
System.out.println("----主线程执行结束----");
运行结果
调用start()方法
***主线程执行***
***线程名***:main
----主线程执行结束----
子线程执行
--- 线程名---:Thread-0,序号:0
--- 线程名---:Thread-0,序号:1
--- 线程名---:Thread-0,序号:2
--- 线程名---:Thread-0,序号:3
--- 线程名---:Thread-0,序号:4
子线程执行
--- 线程名---:Thread-1,序号:0
--- 线程名---:Thread-1,序号:1
--- 线程名---:Thread-1,序号:2
--- 线程名---:Thread-1,序号:3
--- 线程名---:Thread-1,序号:4
调用run()方法
***主线程执行***
***线程名***:main
子线程执行
--- 线程名---:main,序号:0
--- 线程名---:main,序号:1
--- 线程名---:main,序号:2
--- 线程名---:main,序号:3
--- 线程名---:main,序号:4
子线程执行
--- 线程名---:main,序号:0
--- 线程名---:main,序号:1
--- 线程名---:main,序号:2
--- 线程名---:main,序号:3
--- 线程名---:main,序号:4
----主线程执行结束---- //必须等子线程完成后才可以继续运行
注意start()方法和run()方法的区别
start():启动线程start()方法(一旦启动,自动启动子线程,当前线程继续向下执行,不会等子线程);
run() :调用run方法,不可以启动线程,只是对象的普通方法调用,等run方法执行结束,主线程才能继续执行;
2、实现Runnable接口
实现Runnable接口,也必须实现run方法;
案例
public class MyRunnable implements Runnable{
private int num = 5;
@Override
public void run() {
//线程执行的业务方法
System.out.println("子线程执行");
for (int i = 0;i i++){
if(num 0){
System.out.println("--- 线程名---:"+Thread.currentThread().getName()+",序号:"+num--);
public static void main(String[] args) {
//主线程
System.out.println("***主线程执行***");
System.out.println("***线程名***:"+Thread.currentThread().getName());
//创建一个子线程,并启动
MyRunnable runnable1 = new MyRunnable();
//实现Runnable接口方式创建的线程,不能自己启动,只能通过Thread类,将Runnable作为参数传入Thread类的构造方法中,
// 构造线程对象,才可以启动
Thread thread1 = new Thread(runnable1);
thread1.start();
//创建多线程 (如果传入的Runnable参数一样,可以共享资源)
Thread thread2 = new Thread(runnable1);
thread2.start();
System.out.println("----主线程执行结束----");
运行结果
***主线程执行***
***线程名***:main
----主线程执行结束----
子线程执行
子线程执行
--- 线程名---:Thread-0,序号:5
--- 线程名---:Thread-1,序号:4
--- 线程名---:Thread-0,序号:3
--- 线程名---:Thread-1,序号:2
--- 线程名---:Thread-0,序号:1
注意
如果传入的Runnable参数一样,可以共享资源;
3、比较两种创建线程的方式
继承Thread类
编写简单,可直接操作线程
适用于单继承
实现Runnable接口
避免单继承局限性
便于共享资源
4、实现Callable接口
4.1实现Callable接口调用的call方法
创建线程的方式三,实现Callable接口,线程自动调用的时call方法,不是run方法,jdk1.5后才提供;
4.2 FutureTask 类的继承关系
执行 Callable 方式,需要 FutureTask 实现类的支持,用于接收运算结果。
//FutureTask V 是 RunnableFuture V 的实现类
public class FutureTask V implements RunnableFuture V
//RunnableFuture V 接口继承了 Runnable, Future V //所以FutureTask最后需要放到Thread参数中,这里跟继承Runnable方法一样;
public interface RunnableFuture V extends Runnable, Future V ;
类图
4.3 案例
public class MyCallable implements Callable Integer {
@Override
public Integer call() throws Exception {
System.out.println("***子线程执行***");
//执行线程处理方法
int sun = 0;
for (int i = 0; i i++) {
sun+=i;
return sun;
public static void main(String[] args) {
//主线程执行
System.out.println("---主线程执行---");
//创建子线程,不可以自己单独启动,必须借助FutureTask才可以,必须获取子线程执行结果
MyCallable callable = new MyCallable();
FutureTask Integer futureTask = new FutureTask Integer (callable);
//启动线程,只能借助Thread类
Thread thread = new Thread(futureTask);
thread.start();
//获取子线程的执行结果(必须要子线程执行结束,才可以获取结果)
try {
Integer resultSun = futureTask.get(); //接收返回值
System.out.println("五以内的数字之和:"+resultSun);
} catch (Exception e) {
e.printStackTrace();
System.out.println("---主线程结束---");
运行结果
---主线程执行---
***子线程执行***
五以内的数字之和:10 //接收到返回值
---主线程结束---
4.4 Callable和Runnable的区别
1)所在包不同,Callable在java.util.concurrent包下,Runnable在java.lang包;
2)实现的接口方法不同:Callable是重写call方法,Runnable的重写run方法;
3)抛出异常处理不同:Callable是重写call方法,可以抛出异常,但是Runnable是重写run方法不可以抛出异 常,如果抛出线程直接中断;
4)返回值不同:实现Callable接口的线程,可以通过FutureTask获取返回值,但是是实现Runnable接口的线程,无法获取返回值;
以上就是多线程(一)(多线程一定要加锁么)的详细内容,想要了解更多 多线程(一)的内容,请持续关注盛行IT软件开发工作室。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。