Java 并发/多线程教程(七)-创建和启动java线程

简介:       本系列译自jakob jenkov的Java并发多线程教程,个人觉得很有收获。由于个人水平有限,不对之处还望矫正!创建和启动线程在java中创建一个线程如下:Thread thread = new Thread();调用方法start()来启动一个线程:thread.start();         这个例子没有指定线程执行任何代码,线程将会在启动之后停止。

      本系列译自jakob jenkov的Java并发多线程教程,个人觉得很有收获。由于个人水平有限,不对之处还望矫正!

创建和启动线程

在java中创建一个线程如下:

Thread thread = new Thread();

调用方法start()来启动一个线程:

thread.start();

        这个例子没有指定线程执行任何代码,线程将会在启动之后停止。

        有两种方式指定线程应该执行什么代码。第一种方式就是创建一个Thread的子类并覆写run()方法。第二种方式就是创建一个实现Runnable接口的类。

Thread的子类

      第一种方式指定线程执行什么样的代码,就是创建一个Thread的子类,并且覆写run()方法。在run()方法里的代码就是你调用start()方法后,线程要执行的代码。下面是一个创建Thread子类的例子:

public class MyThread extends Thread{

       @Override

        public void run(){

             System.out.println("MyThread running");

        }

}

为了创建并启动上面的线程,你应该这样做:

MyThread myThread = new MyThread();

myThread.start();

start()方法会在线程开始后立马返回,而不是等到run()方法执行完毕。当run()执行时,就会输出“MyThread running”;

当然,你也可以创建一个Thread的匿名子类,如下:

Thread thread = new Thread(){

      @Override

       public void run(){

                System.out.println("Thread Running");

       }

}

thread.start();

上面的例子当线程被调用时会输出文本“Thread Running".

实现Runnable接口

     第二种方式指定线程应该执行什么样的代码,就是创建一个实现java.lang.Runnable接口的类。这个Runnable对象可以被Thread执行。

     下面是一个实现了Runnable接口的例子:

public class MyRunnable implements Runnable{

      @Override

      public void run(){

            System.out.println("MyRunnable running");

      }

}

因为有了Thread线程执行的run()方法,将MyRunnable的一个实例传给Thread的构造方法。

Thread thread = new Thread(new MyRunnable());

thread.start();

    当线程启动时,会调用MyRunnable实例中的run()方法,而不是Thread自己的run()方法。上面的例子会输出”MyRunnable running".

当然,你也可以创建一个匿名的Runnable接口实例:

Runnable myRunnable = new Runnable(){

        @Override

        public void run(){

               System.out.println("Runnable running");

         }

}

Thread thread = new Thread(myRunnable);

thread.start();

Subclass or Runnable?

       没有明确的规则说这两种方式哪一种是最好的。个人倾向于实现Runnable接口。将实现Runable接口的一个实例交给Thread的实例。当由线程池来执行实现Runnable接口的线程实例时,当线程池没有空闲线程可以调试时,可以让这些线程很好的排队。但是如果执行的是实现Thread的子类的线程实例,那么将会很难做到这一点。

       有时,你可能要同时实现Runnable和Thread子类。例如:创建一个Thread的线程可以执行一个或多个Runable实例,这就是线程池的实现方式。

常见的陷阱:调用run()方法而不是start()方法

      当创建和启动一个线程,通常会犯的一个错误就是调用run()方法,而不是start()方法,如下:

Thread newThread = new Thread(MyRunnable());

newThread.run(); // should be start();

起初,你可能没有注意到什么,因为run()正如你期待的那样被执行了。然而,他并不是被你刚创建的线程所执行。而是被创建线程的线程执行。换句话说,就是执行上面两行代码的线程来执行的run()里的方法。调用线程的使用start()方法。

线程名称

       当你创建一个线程时,你可以给这个线程指定名称。线程名可以让你和其他的线程进行区分。举个例子:

Thread thread = new Thread("New Thread"){

       @override

       public void run(){

              System.out.println("run by:"+getName());

      }

}

thread.start();

System.out.println(thread.getName());

注意,字符串“New Thread"作为一个参数传给Thread的构造器,这个字符串就是线程的名称,这个名称可以通过方法getName()来获取到,你也可以传递参数的方式给一个实现Runnable的接口的线程指定线程名称:如下

MyRunnable runnable = new MyRunnable();

Thread thread = new Thread(runnable,"New Thread");

thread.start();

System.out.println(thread.getName());

注意。MyRunnable不是Thread的一个子类,他不能直接调用Thread的getName()方法。

Thread.currentThread()

Thread.currentThread()方法返回线程正在执行的线程。

Thread thread = Thread.currentThread();

只要获取到当前运行线程,你就可以在此基础上进行方法的调用。例如:你可以获取到当前正在执行线程的名称。

String threadName = Thread.currentThread().getName();

Java Thread example

这里有一个小例子。首先输出执行main方法的线程名称。这个线程是由JVM指定的。然后开启10个线程,并以”“+i作为他们的线程名。每个线程输出他们的名字后,然后停止。

public class ThreadExample{

     public static void main(String[] args){

           System.out.println(Thread.currentThread().getName());

           for(int i=0;i<10;i++){

              new Thread(""+i){

                   public void run(){

                       System.out.println("Thread:"+getName()+"running");

                   }

             }.start();

         }

      }

}

注意。线程并不是有序执行的。也就是说线程1并不是第一个执行的线程,这是因为线程的执行原则是并行的,而不是有序的,JVM和操作系统决线程的调度顺序。当他们调度时顺序是不固定的。

目录
相关文章
|
4天前
|
Java 程序员 开发者
Java社招面试题:一个线程运行时发生异常会怎样?
大家好,我是小米。今天分享一个经典的 Java 面试题:线程运行时发生异常,程序会怎样处理?此问题考察 Java 线程和异常处理机制的理解。线程发生异常,默认会导致线程终止,但可以通过 try-catch 捕获并处理,避免影响其他线程。未捕获的异常可通过 Thread.UncaughtExceptionHandler 处理。线程池中的异常会被自动处理,不影响任务执行。希望这篇文章能帮助你深入理解 Java 线程异常处理机制,为面试做好准备。如果你觉得有帮助,欢迎收藏、转发!
48 14
|
5天前
|
Python
python3多线程中使用线程睡眠
本文详细介绍了Python3多线程编程中使用线程睡眠的基本方法和应用场景。通过 `time.sleep()`函数,可以使线程暂停执行一段指定的时间,从而控制线程的执行节奏。通过实际示例演示了如何在多线程中使用线程睡眠来实现计数器和下载器功能。希望本文能帮助您更好地理解和应用Python多线程编程,提高程序的并发能力和执行效率。
34 20
|
7天前
|
安全 Java 程序员
Java 面试必问!线程构造方法和静态块的执行线程到底是谁?
大家好,我是小米。今天聊聊Java多线程面试题:线程类的构造方法和静态块是由哪个线程调用的?构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节有助于掌握Java多线程机制。下期再见! 简介: 本文通过一个常见的Java多线程面试题,详细讲解了线程类的构造方法和静态块是由哪个线程调用的。构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节对掌握Java多线程编程至关重要。
38 13
|
8天前
|
JavaScript NoSQL Java
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
152 96
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
|
8天前
|
安全 Java 开发者
【JAVA】封装多线程原理
Java 中的多线程封装旨在简化使用、提高安全性和增强可维护性。通过抽象和隐藏底层细节,提供简洁接口。常见封装方式包括基于 Runnable 和 Callable 接口的任务封装,以及线程池的封装。Runnable 适用于无返回值任务,Callable 支持有返回值任务。线程池(如 ExecutorService)则用于管理和复用线程,减少性能开销。示例代码展示了如何实现这些封装,使多线程编程更加高效和安全。
|
11天前
|
安全 Java C#
Unity多线程使用(线程池)
在C#中使用线程池需引用`System.Threading`。创建单个线程时,务必在Unity程序停止前关闭线程(如使用`Thread.Abort()`),否则可能导致崩溃。示例代码展示了如何创建和管理线程,确保在线程中执行任务并在主线程中处理结果。完整代码包括线程池队列、主线程检查及线程安全的操作队列管理,确保多线程操作的稳定性和安全性。
|
28天前
|
消息中间件 Java 数据库
自研Java框架 Sunrays-Framework使用教程「博客之星」
### Sunrays-Framework:助力高效开发的Java微服务框架 **Sunrays-Framework** 是一款基于 Spring Boot 构建的高效微服务开发框架,深度融合了 Spring Cloud 生态中的核心技术组件。它旨在简化数据访问、缓存管理、消息队列、文件存储等常见开发任务,帮助开发者快速构建高质量的企业级应用。 #### 核心功能 - **MyBatis-Plus**:简化数据访问层开发,提供强大的 CRUD 操作和分页功能。 - **Redis**:实现高性能缓存和分布式锁,提升系统响应速度。 - **RabbitMQ**:可靠的消息队列支持,适用于异步
自研Java框架 Sunrays-Framework使用教程「博客之星」
|
30天前
|
存储 移动开发 算法
【潜意识Java】Java基础教程:从零开始的学习之旅
本文介绍了 Java 编程语言的基础知识,涵盖从简介、程序结构到面向对象编程的核心概念。首先,Java 是一种高级、跨平台的面向对象语言,支持“一次编写,到处运行”。接着,文章详细讲解了 Java 程序的基本结构,包括包声明、导入语句、类声明和 main 方法。随后,深入探讨了基础语法,如数据类型、变量、控制结构、方法和数组。此外,还介绍了面向对象编程的关键概念,例如类与对象、继承和多态。最后,针对常见的编程错误提供了调试技巧,并总结了学习 Java 的重要性和方法。适合初学者逐步掌握 Java 编程。
52 1
|
30天前
|
前端开发 Java 开发工具
Git使用教程-将idea本地Java等文件配置到gitte上【保姆级教程】
本内容详细介绍了使用Git进行版本控制的全过程,涵盖从本地仓库创建到远程仓库配置,以及最终推送代码至远程仓库的步骤。
39 0
|
30天前
|
Java 数据库连接 数据处理
探究Java异常处理【保姆级教程】
Java 异常处理是确保程序稳健运行的关键机制。它通过捕获和处理运行时错误,避免程序崩溃。Java 的异常体系以 `Throwable` 为基础,分为 `Error` 和 `Exception`。前者表示严重错误,后者可细分为受检和非受检异常。常见的异常处理方式包括 `try-catch-finally`、`throws` 和 `throw` 关键字。此外,还可以自定义异常类以满足特定需求。最佳实践包括捕获具体异常、合理使用 `finally` 块和谨慎抛出异常。掌握这些技巧能显著提升程序的健壮性和可靠性。
47 4