Java进阶-线程的体系结构及创建方法

线程的体系结构

根节点:
	Runnable接口(线程的任务接口,其只有一个抽象方法:void run(),而run方法就是线程需要执行的任务代码)
    
实现类:
	Thread(只有Thread类和Thread类的子类的对象才是线程对象,且Thread类中存在着启动线程的方法start())

线程的创建方法

线程的第一种开启方式

第一种:使用继承
1. 创建一个类MyThread,继承Thread2. 重写父类中的run方法: 
		编写线程对象的任务
4. 创建MyThraed类的对象,并调用start()方法启动线程

代码实现

package com.tan.threadstart;

public class MyThread extends Thread {
//    主动重写父类的run方法,自定义线程任务
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(" MyThread执行的次数: " + i);
        }
    }
}


package com.tan.threadstart;

public class ThreadTest {
    public static void main(String[] args) {
//        创建Thread的子类对象
        MyThread mt = new MyThread();
//        启动线程
        mt.start();

        for (int i = 0; i < 100; i++) {
            System.out.println(" 主线程执行的次数: " + i);
        }
    }
}


线程的第二种开启方式

第二种:实现
1. 创建一个Runnable接口的实现类MyRunnable类的对象(用类实现或者用匿名内部类) ,并重写run方法
2. 创建Thread类对象并把Runnable的实现类MyRunnable类对象传递进去(用到的Thread类中的构造方法:Thread(Runnable target) )
3. 启动线程

代码实现

package com.tan.threadstart;

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(" MyRunnable执行的次数: " + i);
        }
    }
}



package com.tan.threadstart;

public class ThreadTest {
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.start();

        for (int i = 0; i < 100; i++) {
            System.out.println(" 主线程执行的次数: " + i);
        }
    }
}

注意,我们可以发现该方法中Runnable的实现类对象只是传参,使用次数较少,可以使用匿名内部类的方式去创建Runnable的实现类对象,代码如下:

package com.tan.threadstart;


public class ThreadTest {
    public static void main(String[] args) {
//        用匿名内部类创建Runnable的实现类对象,并创建Thread对象
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
//                线程的任务
                for (int i = 0; i < 100; i++) {
                    System.out.println(" Runnable执行的次数: " + i);
                }
            }
        });

//        启动线程
        thread.start();

//        主线程
        for (int i = 0; i < 100; i++) {
            System.out.println(" 主线程执行的次数: " + i);
        }
    }
}

线程的第三种开启方式

第三种:有结果的线程任务
Callable<V> 接口 -> 线程的任务接口
	其中V表示的是线程完成任务后,返回的结果的数据类型
	Callable接口有且仅有一个方法: V call()
    Callable接口和Runable很像,但是Callable接口在任务完成之后可以返回一个结果
    
Runnable接口和FutureTask类和Callable接口和Thread类的关系梳理
	(Callable接口和其他三种类和接口没有继承或者实现的关系,是独立的)
    	1. Runnable接口 是 FutureTask类 的父接口,且也是Thread类的父接口( FutureTask类和Thread类也没关系,只是都实现了Runnable接口)
        2. FutureTask(Callable<V> callable) 
        3. Thread(Runnable target)
    
中间类FutureTask,其有两个构造方法:
	FutureTask(Callable<V> callable)
    FutureTask(Runnable runnable, V result) 
        
开启方式:
		1. 创建Callable的实现类对象,并重写call方法,call和run方法一样,都是线程的任务,但是call在线程任务完成以后可以返回结果
		2. 创建中间桥梁类FutureTask,FutureTaskRunnable接口的实现类,并把任务对象MyCallable类对象传递给FutureTask对象
		3. 创建线程Thread对象,Thread的构造方法的形参可以放Runnable对象
		4. 启动线程
		
注意:
FutureTask类中的V get()方法 : 可以获取线程结束的结果,但是也有阻塞效果,get()需要线程的任务全部执行完毕,才会返回结果,而main方法内的代码会顺序执行,因此会阻塞main方法内后续代码的执行
如果get方法后面还有代码,则会对后续代码产生阻塞效果

代码实现

package com.tan.threadstart;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class ThreadTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
//        创建Callable的实现类对象
        Callable<String> call = new Callable<String>() {
            @Override
            //call和run方法一样,都是线程的任务,但是call在线程任务完成以后可以返回结果
            public String call() throws Exception {
                for (int i = 0; i < 100; i++) {
                    System.out.println("Callable执行的次数: " + i);
                }
                return "It's done.";
            }
        };

//        创建中间桥梁类FutureTask,FutureTask是Runnable接口的实现类
        FutureTask<String> ft = new FutureTask<>(call);



//        创建线程Thread对象,Thread的构造方法的形参可以放Runnable对象
        Thread thread = new Thread(ft);

//        启动线程
        thread.start();

        /*
        FutureTask类中的get方法可以获取线程结束的结果,但是也有阻塞效果
        如果把System.out.println("ft.get() = " + ft.get());放在下面的位置,则其处于main线程内
        而get()又需要子线程的任务全部执行完毕,才会返回结果
        而main方法内的代码会顺序执行,因此会阻塞main方法内后续代码的执行
        因此一定会出现先执行100次Callable的线程任务,输出线程结束的结果:ft.get() = It's done.,最后才会执主线程的任务
         */
//        System.out.println("ft.get() = " + ft.get());

//        在main方法里,在主线程栈里面执行
        for (int i = 0; i < 100; i++) {
            System.out.println("主线程执行的次数: " + i);
        }
        System.out.println("ft.get() = " + ft.get());
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值