java核心学习(二十一) 多线程---创建启动线程的三种方式

   本节开始java多线程编程的学习,对于操作系统、进程、线程的基本概念不再赘述,只是了解java对于多线程编程的支持有哪些。

一、继承Thread类来创建线程

   java语言中使用Thread类来代表线程,代表线程的类可以通过继承Thread类并重写run()方法来实现多线程开发,调用线程类实例的start方法来启动该线程。下面来试一试

 

package ThreadTest;

public class FirstThread extends Thread{
    private int i;
    public void run(){
        for(;i<100;i++){
            System.out.println(getName() + " "+i);
        }
    }
    public static void main(String[] args){
        for(int i = 0; i<10000 ; i++){
            //Thread.currentThread()方法,获取当前线程实例
            System.out.println(Thread.currentThread().getName() + " " +i);
            if(i == 20){
                new FirstThread().start();
                new FirstThread().start();
            }
        }
    }
}

    输出结果可想而知,三个线程交替运行。其中mian线程是Thread-0 和 Thread-1的父亲线程,使用继承Thread类的线程类来创建线程时,多个线程无法共享线程类的实例变量。

二、实现Runnable接口来创建线程类

  Runnable接口中只有一个抽象方法 void run(),是一个函数式接口。如果打开Thread类的代码,就可以发现Thread类也是实现了Runnable接口。

  实现Runnable接口的run()方法的类只能算一个target,只是为线程提供了run方法,要真正创建线程必须调用Thread的构造方法来创建Thread,其实也是使用了Thread来创建线程。

  下面来试一试

package ThreadTest;

public class SecondThread implements Runnable{
    private int i;
    public void run(){
        for(;i<100;i++){
            System.out.println(Thread.currentThread().getName()+ " " +i);
        }
    }
    public static void main(String[] args)
    {
        for(int i = 0;i<100;i++){

            System.out.println(Thread.currentThread().getName()+ " "+ i);
            if(i==20){
                Runnable st = new SecondThread();
                new Thread(st,"自定义名字").start();
            }
        }
    }
}

  

    这是Thread的run方法,可以看到Thread调用了Runnable实现类的run方法。

三、使用Callable 和 Future创建线程

  Callable接口只有一个call()抽象方法,与run()不同的是call()有返回值,可以抛出异常

  下图是Callable接口定义

  

  泛型V代表了call方法的返回值类型

  那么如何把实现了Callable接口的类的call方法当做线程执行体呢,如何获取call方法的返回值呢?

  这需要用到Future,Future接口代表call()方法的返回值,调用Future实例的get方法可以去的返回值,对应于Callable接口,Future也支持泛型。

  还需要用到FutureTask类,这个类实现了Future接口和Runnable,可以获取到返回值,也可以作为线程创建的target

  FutureTask的构造器

  FutureTask的run方法

  下面用一下

package ThreadTest;

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

public class ThirdThread{
    public static void main(String[] args){
        ThirdThread tt = new ThirdThread();
        FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int i =0;
                for(;i<100;i++){
                    System.out.println(Thread.currentThread().getName() + " " + i);
                }
                return i;
            }
        });
        for (int i = 0;i<100;i++){
            System.out.println(Thread.currentThread().getName()+" "+i);
            if(i == 20){
                new Thread(task,"带返回值的线程").start();
            }
            try {
                System.out.println("子线程返回值:" + task.get());
            }catch (Exception ex){
                ex.printStackTrace();
            }
        }
    }
}

    这里要注意,调用FutureTask方法的get方法时,当前线程在取得返回值之前会被阻塞。

    通常使用后两种方式来创建线程

时间: 2024-10-20 03:11:41

java核心学习(二十一) 多线程---创建启动线程的三种方式的相关文章

java创建线程的三种方式及其对比

Java中创建线程主要有三种方式: 一.继承Thread类创建线程类 (1)定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务.因此把run()方法称为执行体. (2)创建Thread子类的实例,即创建了线程对象. (3)调用线程对象的start()方法来启动该线程. package com.thread; public class FirstThreadTest extends Thread{ int i = 0; //重写run方法,run方法的方

java创建线程的三种方式及其对照

Java中创建线程主要有三种方式: 一.继承Thread类创建线程类 (1)定义Thread类的子类.并重写该类的run方法,该run方法的方法体就代表了线程要完毕的任务.因此把run()方法称为运行体. (2)创建Thread子类的实例,即创建了线程对象. (3)调用线程对象的start()方法来启动该线程. package com.thread; public class FirstThreadTest extends Thread{ int i = 0; //重写run方法.run方法的方

Java反射机制(创建Class对象的三种方式)

1:SUN提供的反射机制的类: java.lang.Class<T> java.lang.reflect.Constructor<T> java.lang.reflect.Field java.lang.reflect.Method java.lang.reflect.Modifier 2:什么是反射 JAVA反射机制是在运行状态中,对于任意一个类.都能都知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称

Java实现线程的三种方式和区别

Java实现线程的三种方式和区别 Java实现线程的三种方式: 继承Thread 实现Runnable接口 实现Callable接口 区别: 第一种方式继承Thread就不能继承其他类了,后面两种可以: 使用后两种方式可以多个线程共享一个target: Callable比Runnable多一个返回值,并且call()方法可以抛出异常: 访问线程名,第一种直接使用this.getName(),后两种使用Thread.currentThread().getName(). 下面我们通过代码来看一下实现

并发编程(壹):创建线程的三种方式及其对比

创建线程的三种方式及其对比 1. 继承 Thread类 (1). 继承Thread类.并重写run()方法,该方法无参数,无返回值: (2). 创建子类实例,并实例化对象: (3). 通过start()方法启动,注意:不是通过run()方法启动. public class ThreadDemo extends Thread{ public void run(){ System.out.println("继承Thread创建线程的."); } } public class ThreadA

创建线程的三种方式

创建线程的三种方式 第一种:通过NSThread的对象方法 第二种:通过NSThread的类方法 第三种:通过NSObject的方法 准备在后台线程调用的方法 longOperation: - (void)longOperation:(id)obj { NSLog(@"%@ - %@", [NSThread currentThread], obj); } 方式1:alloc / init - start - (void)threadDemo1 { NSLog(@"before

spring中创建bean对象的三种方式以及作用范围

时间:2020/02/02 一.在spring的xml配置文件中创建bean对象的三种方式: 1.使用默认构造函数创建.在spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他属性和标签时采用的就是默认构造函数创建bean对象,此时如果类中没有默认构造函数函数,则对象无法创建. <bean id="one" class="sdnu.machi.one"></bean> 如果one.class中没有默认构造函数则会报

JDBC 创建连接对象的三种方式

创建连接对象的三种方式 //第一种方式 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb?user=root&password=root") ; //第二种方式 //读取properties文件 Properties pro = new Properties() ; InputStream in = JdbcDemo3.class.getClassLoader().ge

Android-创建启动线程的两种方式

方式一:成为Thread的子类,然后在Thread的子类.start 缺点:存在耦合度(因为线程任务run方法里面的业务逻辑 和 线程启动耦合了) 缺点:Cat extends Thread {} 后无法在继承其他的类了 注意:?? Cat一旦继承Thread,Cat就属于线程对象 示例: package android.java.thread04; /** * 定义线程的第一种方式 成为Thread的子类 */ class Cat extends Thread { @Override publ