Java多线程学习

Java实现多线程的四种方式

1:通过继承Thread类实现

步骤:1.创建Thread线程类的一个子类,同时要重写Thread类的run()方法

           2.创建该子类的实例对象,并通过start()方法启动线程

package com.lin;

public class Thread01 extends Thread{

    String name;
    public Thread01(String name) {
        this.name = name;
    }

    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(name + "运行 :" + i);
        }
    }


}

测试类:

package com.lin;

public class Test01 {

    public static void main(String[] args) {
        Thread01 thread01 = new Thread01("A线程");
        Thread01 thread02 = new Thread01("B线程");
        thread01.start();
        thread02.start();
    }


}

输出

第一次运行:

B线程运行 :0
A线程运行 :0
B线程运行 :1
B线程运行 :2
B线程运行 :3
B线程运行 :4
A线程运行 :1
A线程运行 :2
A线程运行 :3
A线程运行 :4

第二次运行:

B线程运行 :0
A线程运行 :0
B线程运行 :1
A线程运行 :1
A线程运行 :2
A线程运行 :3
A线程运行 :4
B线程运行 :2
B线程运行 :3
B线程运行 :4

每次运行的输出结果不同

注意:

        start()方法调用后不是立即执行多线程代码,而是让这个线程变成可运行态,什么时候运行是由操作系统决定的,从程序的运行结果来看,多线程程序是乱序执行的

2:通过实现Runnable接口

步骤:

1:创建Runnable接口的实现类,并重写接口中的run()方法

2:创建Runnable接口的实现类对象

3:使用Thread有参构造方法创建线程实例,并将Runnable接口的实现类的实例对象作为参数传入

4:调用线程实例的start()方法启动线程

package com.lin;

public class Thread02 implements Runnable{

    String name;
    public Thread02(String name){
        this.name = name;
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(name+"运行 :" + i);
        }
    }
}
package com.lin;

public class Test02 {
    public static void main(String[] args) {
        Thread02 t01 = new Thread02("A线程");
        Thread02 t02 = new Thread02("B线程");
        Thread thread01 = new Thread(t01);
        Thread thread02 = new Thread(t02);
        thread01.start();
        thread02.start();
    }
}

运行结果:

A线程运行 :0
B线程运行 :0
A线程运行 :1
B线程运行 :1
B线程运行 :2
B线程运行 :3
B线程运行 :4
A线程运行 :2
A线程运行 :3
A线程运行 :4

再次运行:

A线程运行 :0
B线程运行 :0
A线程运行 :1
A线程运行 :2
A线程运行 :3
A线程运行 :4
B线程运行 :1
B线程运行 :2
B线程运行 :3
B线程运行 :4

3:通过实现Callable接口

通过Thread类和实现Runnable接口实现多线程时,因为要重写run()方法,run()方法没有返回值,因此无法通过多个线程中来获取返回值

通过Callable可以实现既可以创建多线程又可以有返回值的需求

步骤:

1:创建一个Callable接口的实现类,同时重写Callable接口的call()方法

2:创建Callable接口的实现类对象

3:通过FutureTask线程结果处理类的有参构造方法来封装Callable接口实现类对象

4:使用参数为FutureTask类对象的Thread有参构造方法创建Thread线程实例

5:调用线程实例的start()方法启动线程

package com.lin;

import java.util.concurrent.Callable;

public class Thread03 implements Callable {
    private String name;
    public Thread03(String name){
        this.name = name;
    }

    @Override
    public Object call() throws Exception {
        int i = 0;
        for (i = 0; i < 5; i++) {
            System.out.println(name+"运行: " + i);
        }
        return i;
    }
}

测试类:

package com.lin;

import java.util.concurrent.FutureTask;

public class Test03{
    public static void main(String[] args) throws Exception{
        Thread03 thread01 = new Thread03("A线程");
        Thread03 thread02 = new Thread03("B线程");
        //使用FutureTask封装Callable接口
        FutureTask<Object>ft1 = new FutureTask<Object>(thread01);
        FutureTask<Object>ft2 = new FutureTask<Object>(thread02);
        //使用Thread(Runnable target,String name)的有参构造方法创建线程对象
        Thread thread1 = new Thread(ft1,"thread1");
        Thread thread2 = new Thread(ft2,"thread2");
        thread1.start();
        thread2.start();
        System.out.println("thread01返回值:"+ft1.get());
        System.out.println("thread02返回值:"+ft2.get());

    }
}

输出结果:

B线程运行: 0
A线程运行: 0
B线程运行: 1
A线程运行: 1
B线程运行: 2
B线程运行: 3
B线程运行: 4
A线程运行: 2
A线程运行: 3
A线程运行: 4
thread01返回值:5
thread02返回值:5

Thread和Runnable的区别

实现Runnable接口比继承Thread类所具有的优势

1:适合多个相同的程序代码的线程去处理同一个资源

2:避免了Java单继承的限制

3:增加了程序的健壮性,代码可以被多个线程共享,代码和数据独立

4:线程池只能放入Runnable和Callablel线程,不能直接放入继承Thread的类

注:main方法也是一个线程

在Java中,每次程序运行至少启动2个线程,一个是main线程,一个是垃圾收集线程,

4.通过线程池创建多线程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值