新手学JAVA(十)-多线程----线程的创建和启动

简介:

Java使用Thread类代表线程,所有的线程对象都必须是Thread类或者其子类的实例。每个下次你哼的作用是完成一定的任务,实际上就是执行一段程序流(一段顺序执行的代码)。Java使用线程执行体来代表这段程序流

    在Java线程的创建有三种方式
    

通过继承Thread类创建线程类


步骤如下

  1. 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务。因此把run()方法称为线程执行体。
  2. 创建Thread子类的实例,即创建了线程的对象。
  3. 调用线程对象的start()方法来启动线程。

/**
 * 通过继承Thread类创建线程类
 * @author Administrator
 *
 */
public class FirstThread extends Thread{

    private int i;
    
    public void run(){
        for(i=0;i<100;i++){
            System.out.println(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){
                new FirstThread().start();
                new FirstThread().start();
            }
        
        }
    }
}

    

实现Runnable接口创建线程类


步骤如下:

  1. 定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法体同样是该线程的线程执行体。
  2. 创建Runnable实现类的实例,并以此实例作为Threadtarget来创建Thread对象,该Thread对象才是真正的线程对象。
  3. 调用线程对象的start()方法来启动该线程。
/**
 * 通过实现Runnable接口来创建线程类
 * @author Administrator
 *
 */
public class SecondThread implements Runnable{
    
    private int i;
    
    public void run()
    {
        for(i=0;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){
                SecondThread st=new SecondThread();
                new Thread(st,"新线程1").start();
                new Thread(st,"新线程2").start();
            }
        
        }
    }
}

    

使用Callable和Future创建线程


步骤如下:

  1. 创建Callable实现类的实例。并实现call()方法,该call()方法将作为线程执行体,且该call()方法有返回值,在创建Callable实现类的实例。从Java8开始,可以直接使用Lambda表达式创建Callable对象。
  2. 使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Call对象的Call()方法的返回值。
  3. 使用FutureTask对象作为Thread对象的target创建并启动新线程。
  4. 调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;


/**
 * 使用Callable和Future创建线程
 * @author Administrator
 *
 */
public class ThirdThead implements Callable<Integer>{

    
    /**
     * @param args
     */
    public static void main(String[] args) {
        ThirdThead rt=new ThirdThead();
        
        FutureTask<Integer> task= new FutureTask<Integer>(rt);
            
        for(int i=0;i<100;i++){
            System.out.println(Thread.currentThread().getName() + "循环变量i的值: " +i);
            if(i==20){
                new Thread(task,"有返回值的线程").start();
            }
        }
        
        try{
            System.out.println("子线程的返回值:"+task.get());
        }catch(Exception ex){
            ex.printStackTrace();
        }
    }

    @Override
    public Integer call() throws Exception {
        int i=0;
        for(i=0;i<100;i++){
            System.out.println(Thread.currentThread().getName() + "循环变量i的值: " +i);
        }
        return i;
    }

}

    

三种创建方式的对比


    通过继承Thread类或实现Runnable、Callable接口都可以实现多线程。不过实现Runnable和实现Callable的方式基本相同,只不过Callable有返回值,并可以抛出异常。因此把Runnable、Callable归为一类。这种实现方式和继承Thread方式的差别如下:

采用实现Runnable、Callable接口的方式创建多线程优缺点:

  1. 显示只是实现了RunnableCallable接口,还可以实现其他的继承其他的类。
  2. 这种情况下, 多线程可以共享同一个target对象,非常适合多个相同线程来处理同一份资源,从而可以更好的将CPU、代码和数据分开,形成清晰的模型,很好的体现了面向对象的思想。
  3. 劣势:编程比较复杂,而且如果想要访问当前线程的话,必须使用Thread.currentThread()方法。

采用继承Thread类的方式创建多线程优缺点:

  1. 优势:编写简单,如果需要访问当前线程,不需要用Thread.currentThread()方法,直接使用this即可获取当前线程。
  2. 劣势:因为线程已经继承了Thread类,所以不能再继承其他父类。

    
    
    综上分析:推荐使用实现Runnable接口、Callable接口的方式来实现多线程。

相关文章
|
1天前
|
Java
Java中的多线程编程:基础知识与实践
【5月更文挑战第13天】在计算机科学中,多线程是一种使得程序可以同时执行多个任务的技术。在Java语言中,多线程的实现主要依赖于java.lang.Thread类和java.lang.Runnable接口。本文将深入探讨Java中的多线程编程,包括其基本概念、实现方法以及一些常见的问题和解决方案。
|
1天前
|
安全 算法 Java
深入理解Java并发编程:线程安全与性能优化
【5月更文挑战第13天】 在Java开发中,并发编程是一个复杂且重要的领域。它不仅关系到程序的线程安全性,也直接影响到系统的性能表现。本文将探讨Java并发编程的核心概念,包括线程同步机制、锁优化技术以及如何平衡线程安全和性能。通过分析具体案例,我们将提供实用的编程技巧和最佳实践,帮助开发者在确保线程安全的同时,提升应用性能。
10 1
|
2天前
|
Java 调度
Java一分钟之线程池:ExecutorService与Future
【5月更文挑战第12天】Java并发编程中,`ExecutorService`和`Future`是关键组件,简化多线程并提供异步执行能力。`ExecutorService`是线程池接口,用于提交任务到线程池,如`ThreadPoolExecutor`和`ScheduledThreadPoolExecutor`。通过`submit()`提交任务并返回`Future`对象,可检查任务状态、获取结果或取消任务。注意处理`ExecutionException`和避免无限等待。实战示例展示了如何异步执行任务并获取结果。理解这些概念对提升并发性能至关重要。
17 5
|
2天前
|
安全 Java 调度
深入理解Java并发编程:线程安全与性能优化
【5月更文挑战第12天】 在现代软件开发中,多线程编程是提升应用程序性能和响应能力的关键手段之一。特别是在Java语言中,由于其内置的跨平台线程支持,开发者可以轻松地创建和管理线程。然而,随之而来的并发问题也不容小觑。本文将探讨Java并发编程的核心概念,包括线程安全策略、锁机制以及性能优化技巧。通过实例分析与性能比较,我们旨在为读者提供一套既确保线程安全又兼顾性能的编程指导。
|
3天前
|
Java
Java一分钟:线程协作:wait(), notify(), notifyAll()
【5月更文挑战第11天】本文介绍了Java多线程编程中的`wait()`, `notify()`, `notifyAll()`方法,它们用于线程间通信和同步。这些方法在`synchronized`代码块中使用,控制线程执行和资源访问。文章讨论了常见问题,如死锁、未捕获异常、同步使用错误及通知错误,并提供了生产者-消费者模型的示例代码,强调理解并正确使用这些方法对实现线程协作的重要性。
13 3
|
3天前
|
安全 算法 Java
Java一分钟:线程同步:synchronized关键字
【5月更文挑战第11天】Java中的`synchronized`关键字用于线程同步,防止竞态条件,确保数据一致性。本文介绍了其工作原理、常见问题及避免策略。同步方法和同步代码块是两种使用形式,需注意避免死锁、过度使用导致的性能影响以及理解锁的可重入性和升级降级机制。示例展示了同步方法和代码块的运用,以及如何避免死锁。正确使用`synchronized`是编写多线程安全代码的核心。
55 2
|
3天前
|
安全 Java 调度
Java一分钟:多线程编程初步:Thread类与Runnable接口
【5月更文挑战第11天】本文介绍了Java中创建线程的两种方式:继承Thread类和实现Runnable接口,并讨论了多线程编程中的常见问题,如资源浪费、线程安全、死锁和优先级问题,提出了解决策略。示例展示了线程通信的生产者-消费者模型,强调理解和掌握线程操作对编写高效并发程序的重要性。
43 3
|
3天前
|
安全 Java
深入理解Java并发编程:线程安全与性能优化
【5月更文挑战第11天】在Java并发编程中,线程安全和性能优化是两个重要的主题。本文将深入探讨这两个方面,包括线程安全的基本概念,如何实现线程安全,以及如何在保证线程安全的同时进行性能优化。我们将通过实例和代码片段来说明这些概念和技术。
3 0
|
3天前
|
Java 调度
Java并发编程:深入理解线程池
【5月更文挑战第11天】本文将深入探讨Java中的线程池,包括其基本概念、工作原理以及如何使用。我们将通过实例来解释线程池的优点,如提高性能和资源利用率,以及如何避免常见的并发问题。我们还将讨论Java中线程池的实现,包括Executor框架和ThreadPoolExecutor类,并展示如何创建和管理线程池。最后,我们将讨论线程池的一些高级特性,如任务调度、线程优先级和异常处理。
|
4天前
|
安全 Java
【JAVA进阶篇教学】第十篇:Java中线程安全、锁讲解
【JAVA进阶篇教学】第十篇:Java中线程安全、锁讲解