java多线程的3种实现方式

多线程相关的问题

1.什么是进程?

? 正在执行的程序

2.什么是线程?

? 进程的子单位,一个能够完成独立功能的执行路径

3.为什么需要开启多线程?

  • 当执行某些耗时操作的任务的时候需要开启多线程,防止线程阻塞
  • 能够让两个任务看起来像是在同时执行
  • 提高CPU的使用率,进而提高进程和内存的使用率

4.为什么开启多线程会同时执行?

? 因为CPU切换执行的速度太快了,肉眼无法差距

5.开启多线程是不是越多越好,提高了效率还是降低了效率?

? 不是,线程越多,效率越慢,但是太少,浪费CPU资源,所以,合理利用CPU

6.并发和并行的区别

  • 并发 --> 在同一个时间段下同时执行多个线程,看起来像同时执行
  • 并行 --> 在同一个时间刻度下(不能够在分割的时间单位)执行多个线程,本质就上就是同时执行

CPU在某一个最小的时间刻度单位下,执行的是一个进程的一个线程的一个不可再分割的原子性语句

线程开启方式

Java提供了三种创建线程方法:

? 1.继承Thread类的方式

? 2.实现Runnable的方式

? 3.通过 Callable 和 Future 创建线程。

方式一:继承Thread类

? 1.自定义类MyThread继承Thread类。3
? 2.MyThread类里面重写run()方法。
? 3.创建线程对象。
? 4.启动线程。
注意:
? 1、启动线程使用的是start()方法而不是run()方法
? 2、线程能不能多次启动

线程对象调用 run方法和调用start方法区别?

  • 线程对象调用run方法不开启线程。仅是对象调用方法。
  • 线程对象调用start开启线程,并让jvm调用run方法在开启的线程中执行

代码演示使用方式一开启线程

// 方式二:实现Runnable接口
class CalculateRunnable implements Runnable {
    private int m;
    private int n;
    public CalculateRunnable(int m, int n) {
        super();
        this.m = m;
        this.n = n;
    }
    public CalculateRunnable() {
        super();
    }
    @Override
    public void run() {
        int sum = 0;
        for (int i = m; i <= n; i++) {
            sum += i;
            System.out.println("CalculateRunnable子线程: " + i);
        }
        System.out.println(m + "~" + n + "的和: " + sum);
    }
} 

方式二:实现Runnable接口

? 1.自定义类MyRunnable实现Runnable接口
? 2.重写run()方法
? 3.创建MyRunnable类的对象
? 4.创建Thread类的对象,并把步骤3创建的对象作为构造参数传递
? 5.启动线程

实现接口方式的好处
可以避免由于Java单继承带来的局限性。
适合多个相同程序的代码去处理同一个资源的情况,把线程同程序的代码,数据有效分离,较好的体现了面向对象的设计思想。

代码演示方式二开启线程

// 方式一:继承Thread类
class CopyThread extends Thread {
    private File srcFile;
    private File descFile;

    public CopyThread() {
        super();
    }

    public CopyThread(File srcFile, File descFile) {
        super();
        this.srcFile = srcFile;
        this.descFile = descFile;
    }

    @Override
    public void run() {
        // main方法怎么写,这里就怎么写
        copy(srcFile, descFile);
    }

    public void copy(File srcFile, File descFile) {
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(descFile))){
            byte[] bys = new byte[1024];
            int len = 0;
            while ((len = bis.read(bys)) != -1) {
                bos.write(bys, 0, len);
                bos.flush();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
主方法调用
    public static void main(String[] args) {
        CopyThread ct = new CopyThread(new File("Test.java"), new File("Test.txt"));
        CalculateRunnable cr = new CalculateRunnable(1, 200);
        Thread t = new Thread(cr);
        ct.start();
        t.start();
        for (int i = 0; i < 100; i++) {
            System.out.println("main线程: " + i);
        }
    }

方式三: Callable 和 Future 创建线程。

  • 创建 Callable 接口的实现类,并实现 call() 方法,该 call() 方法将作为线程执行体,并且有返回值。
  • 创建 Callable 实现类的实例,使用 FutureTask 类来包装 Callable 对象,该 FutureTask 对象封装了该 Callable 对象的 call() 方法的返回值。
  • 使用 FutureTask 对象作为 Thread 对象的 target 创建并启动新线程。
  • 调用 FutureTask 对象的 get() 方法来获得子线程执行结束后的返回值。

继承Thread和实现Runnable的方式的特点:

? 1.没有返回结果

? 2.没有异常

Callable和Runnable的区别:

? 1.Runnable无返回值,没有异常抛出的

? 2.Callable可以在启动线程中获取返回值, 以及接受子线程的异常

线程间的数据传递:线程通信

? A线程中开启了B线程

? A --> B 通过构造方法

? B --> A 通过Callable方式

public class CallableDemo{
    public static void main(String[] args) {
        FutureTask<Integer> task = new FutureTask<>(new CalculateCallable(0,100));
        Thread t = new Thread(task);
        t.start();

        try {
            Integer i = task.get();
            System.out.println("计算结果: " + i);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("程序结束");
    }
}
class CalculateCallable implements Callable<Integer> {

    private int m;
    private int n;

    public CalculateCallable() {
        super();
    }

    public CalculateCallable(int m, int n) {
        super();
        this.m = m;
        this.n = n;
    }

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = m; i <= n; i++) {
            System.out.println("子线程: " + i);
            sum += i;
            throw new NullPointerException("空指针异常!");
        }
        return sum;
    }
}

原文地址:https://www.cnblogs.com/zhiwenxi/p/11407857.html

时间: 2024-10-11 07:06:53

java多线程的3种实现方式的相关文章

Java多线程的两种实现方式:继承Thread类 &amp; 实现Runable接口

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! 创建和启动线程的两种传统方式: Java提供了线程类Thread来创建多线程的程序.其实,创建线程与创建普通的类的对象的操作是一样的,而线程就是Thread类或其子类的实例对象.每个Thread对象描述了一个单独的线程.要产生一个线程,有两种方法: ◆需要从Java.lang.Thread类派生一个新的线程类,重载它的run()方法: ◆实现Runnalbe接口,重载Runnalbe接口中的run()方法.

Java多线程的两种实现方式的区别以及深刻同步问题中的锁对象

首先我们知道创建线程有两种方式: 1.继承Thread类:2.实现Runnable接口. 但是这两这并非完全一样的.下面谈谈区别: 因为Java并不支持多继承的(接口是可以多继承接口的.不过一般我们不提),但支持多实现.当一个类继承了父类,就不能再继承Thread类,只能通过实现接口的形式创建线程. 继承Runnable接口更加符合面向对象的思想.线程分为两部分,一是线程对象,二是线程任务.继承Thread类,线程对象和线程任务(run方法内的代码)耦合在一起.一旦创建了Thread类的子类对象

java多线程的几种实现方式记录

传统的实现线程的方式为三种,分别为继承Thread类,重写run()方法:实现Runable接口,重写run()方法:实现callable接口,重写call()方法:下面来记录一下最基本的三种编码实现. 一.继承Thread public class ExtendsThread extends Thread{ public void run(){ System.out.println("Hello Thread"); } public static void main(String[]

java 多线程编程三种实现方式

一种是继承Thread类,一种是实现Runable接口,还有一种是实现callable接口: 有博主说只有前面2种方式,我个人愚见是三种,主要详细介绍下callable的使用: 三种线程的我的个人理解: thread 是最简单的,简单粗暴也是最基础的,复写run()方法,start启动就好了: runable 是thread基础上的改进版本runable 主要的贡献在于实现了资源的共享,比如说在线选座的座位资源就需要共享这个时候就一定要使用runable,但是他也需要thread 的帮忙: ca

java多线程的4种实现方式

1,继承Thread类,重写run方法: public class Thread01 extends Thread{ public Thread01(){ } public void run(){ System.out.println(Thread.currentThread().getName()); } public static void main(String[] args){ Thread01 thread01 = new Thread01(); thread01.setName("继

Java 多线程的两种实现方式

继承Thead class IphoneThread extends Thread { public int iphone = 5; public String user; public IphoneThread(String str) { user = str; } @Override public void run() { while (iphone != 0) { iphone--; System.out.println(user + " get one and left iphone n

【Java多线程】两种基本实现框架

Java多线程学习1——两种基本实现框架 一.前言 当一个Java程序启动的时候,一个线程就立刻启动,改程序通常也被我们称作程序的主线程.其他所有的子线程都是由主线程产生的.主线程是程序开始就执行的,并且程序最终是以主线程的结束而结束的. Java编写程序都运行在在Java虚拟机(JVM)中,在JVM的内部,程序的多任务是通过线程来实现的.每用Java命令启动一个Java应用程序,就会启动一个JVM进程.在同一个JVM进程中,有且只有一个进程,就是它自己.在这个JVM环境中,所有程序代码的运行都

JavaLearning:多线程的两种实现方式

第一种 继承Thread类 package org.fan.threaddemo; public class MyThread extends Thread{ private String name; public MyThread(String name){ this.name=name; } public void run(){//覆写run()方法 for(int i=0;i<30;i++){ System.out.println("Thread运行:"+this.name

实现Java多线程的三种方式

1. JAVA多线程实现方式    JAVA多线程实现方式主要有三种: 继承Thread类 实现Runnable接口 使用ExecutorService.Callable.Future实现有返回结果的多线程. 其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的. 2. 继承Thread类实现多线程 继承Thread类的方法尽管被我列为一种多线程实现方式,但 Thread本质上也是实现了Runnable接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过Thread