IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java进阶-线程的体系结构及创建方法 -> 正文阅读

[Java知识库]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());
    }
}

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-02-19 01:00:55  更:2022-02-19 01:02:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:54:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码