java 线程创建多线程详解

Java 线程类也是一个 object 类,它的实例都继承自 java.lang.Thread 或其子类。 可以用如下方式用 java 中创建一个线程,执行该线程可以调用该线程的 start()方法:

Tread thread = new Thread();
thread.start();

在上面的例子中,我们并没有为线程编写运行代码,因此调用该方法后线程就终止了。

编写线程运行时执行的代码有两种方式:一种是创建 Thread 子类的一个实例并重写 run 方法,第二种是创建类的时候实现 Runnable 接口。接下来我们会具体讲解这两种方法:

创建 Thread 的子类

创建 Thread 子类的一个实例并重写 run 方法,run 方法会在调用 start()方法之后被执行。可以用如下方式创建并运行上述 Thread 子类例子如下:

public class MyThread extends Thread {
  public void run(){
   System.out.println("MyThread running");
  }
}
MyThread myThread = new MyThread();
myTread.start();

一旦线程启动后 start 方法就会立即返回,而不会等待到 run 方法执行完毕才返回。就好像 run 方法是在另外一个 cpu 上执行一样。当 run 方法执行后,将会打印出字符串 MyThread running。

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

Thread thread = new Thread(){
  public void run(){
   System.out.println("Thread Running");
  }
};
thread.start();

当新的线程的 run 方法执行以后,计算机将会打印出字符串”Thread Running”。

实现 Runnable 接口

第二种编写线程执行代码的方式是新建一个实现了 java.lang.Runnable 接口的类的实例,实例中的方法可以被线程调用。下面给出例子:

public class MyRunnable implements Runnable {
  public void run(){
  System.out.println("MyRunnable running");
  }
}

为了使线程能够执行 run()方法,需要在 Thread 类的构造函数中传入 MyRunnable 的实例对象。示例如下:

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

当线程运行时,它将会调用实现了 Runnable 接口的 run 方法。上例中将会打印出”MyRunnable running”。

同样,也可以创建一个实现了 Runnable 接口的匿名类,如下所示:

Runnable myRunnable = new Runnable(){
  public void run(){
   System.out.println("Runnable running");
  }
}
Thread thread = new Thread(myRunnable);
thread.start();

创建子类还是实现 Runnable 接口?

对于这两种方式哪种好并没有一个确定的答案,它们都能满足要求。就我个人意见,我更倾向于实现 Runnable 接口这种方法。因为线程池可以有效的管理实现了 Runnable 接口的线程,如果线程池满了,新的线程就会排队等候执行,直到线程池空闲出来为止。而如果线程是通过实现 Thread 子类实现的,这将会复杂一些。

有时我们要同时融合实现 Runnable 接口和 Thread 子类两种方式。例如,实现了 Thread 子类的实例可以执行多个实现了 Runnable 接口的线程。一个典型的应用就是线程池。

常见错误:调用 run()方法而非 start()方法

创建并运行一个线程所犯的常见错误是调用线程的 run()方法而非 start()方法,如下所示:

Thread newThread = new Thread(MyRunnable());
newThread.run();  //should be start();

起初你并不会感觉到有什么不妥,因为 run()方法的确如你所愿的被调用了。但是,事实上,run()方法并非是由刚创建的新线程所执行的,而是被创建新线程的当前线程所执行了。也就是被执行上面两行代码的线程所执行的。想要让创建的新线程执行 run()方法,必须调用新线程的 start 方法。

线程名

当创建一个线程的时候,可以给线程起一个名字。它有助于我们区分不同的线程。例如:如果有多个线程写入 System.out,我们就能够通过线程名容易的找出是哪个线程正在输出。例子如下:

MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable, "New Thread");
thread.start();
System.out.println(thread.getName());

需要注意的是,因为 MyRunnable 并非 Thread 的子类,所以 MyRunnable 类并没有 getName()方法。可以通过以下方式得到当前线程的引用:

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

线程代码举例:

这里是一个小小的例子。首先输出执行main()方法线程名字。这个线程 JVM 分配的。然后开启 10 个线程,命名为 1~10。每个线程输出自己的名字后就退出。

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 和操作系统一起决定了线程的执行顺序,他和线程的启动顺序并非一定是一致的。

以上就是对Java 线程创建的资料整理,后续继续补充相关资料,谢谢大家对本站的支持!

(0)

相关推荐

  • java 多线程-锁详解及示例代码

    自 Java 5 开始,java.util.concurrent.locks 包中包含了一些锁的实现,因此你不用去实现自己的锁了.但是你仍然需要去了解怎样使用这些锁. 一个简单的锁 让我们从 java 中的一个同步块开始: public class Counter{ private int count = 0; public int inc(){ synchronized(this){ return ++count; } } } 可以看到在 inc()方法中有一个 synchronized(th

  • 详解Java多线程编程中互斥锁ReentrantLock类的用法

    0.关于互斥锁 所谓互斥锁, 指的是一次最多只能有一个线程持有的锁. 在jdk1.5之前, 我们通常使用synchronized机制控制多个线程对共享资源的访问. 而现在, Lock提供了比synchronized机制更广泛的锁定操作, Lock和synchronized机制的主要区别: synchronized机制提供了对与每个对象相关的隐式监视器锁的访问, 并强制所有锁获取和释放均要出现在一个块结构中, 当获取了多个锁时, 它们必须以相反的顺序释放. synchronized机制对锁的释放是

  • Java 多线程学习详细总结

    目录(?)[-] 一扩展javalangThread类 二实现javalangRunnable接口 三Thread和Runnable的区别 四线程状态转换 五线程调度 六常用函数说明 使用方式 为什么要用join方法 七常见线程名词解释 八线程同步 九线程数据传递 本文主要讲了java中多线程的使用方法.线程同步.线程数据传递.线程状态及相应的一些线程函数用法.概述等. 首先讲一下进程和线程的区别: 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1

  • java多线程-同步块实例讲解

    java多线程-同步块 Java 同步块(synchronized block)用来标记方法或者代码块是同步的.Java 同步块用来避免竞争.本文介绍以下内容: Java 同步关键字(synchronzied) 实例方法同步 静态方法同步 实例方法中同步块 静态方法中同步块 Java 同步示例 Java 同步关键字(synchronized) Java 中的同步块用 synchronized 标记.同步块在 Java 中是同步在某个对象上.所有同步在一个对象上的同步块在同时只能被一个线程进入并执

  • java 实现多线程的方法总结

    java 实现多线程的三种方法 在java中,有三种方法可以实现多线程.第一种方法:继承Thread类,重写run函数.第二种方法:实现Runnable接口,重写run函数.第三种方法:实现Callable接口,重写call函数.本文章将通过实例讲解这三种方法如何实现多线程.需要的可以参考一下.  (1)继承Thread类,重写run函数. class xx extends Thread{ public void run(){ Thread.sleep(1000) //线程休眠1000毫秒,sl

  • Java 高并发二:多线程基础详细介绍

    本系列基于炼数成金课程,为了更好的学习,做了系列的记录. 本文主要介绍 1.什么是线程 2.线程的基本操作 3.守护线程 4.线程优先级 5.基本的线程同步操作 1. 什么是线程 线程是进程内的执行单元 某个进程当中都有若干个线程. 线程是进程内的执行单元. 使用线程的原因是,进程的切换是非常重量级的操作,非常消耗资源.如果使用多进程,那么并发数相对来说不会很高.而线程是更细小的调度单元,更加轻量级,所以线程会较为广泛的用于并发设计. 在Java当中线程的概念和操作系统级别线程的概念是类似的.事

  • 详解Java多线程编程中LockSupport类的线程阻塞用法

    LockSupport是用来创建锁和其他同步类的基本线程阻塞原语. LockSupport中的park() 和 unpark() 的作用分别是阻塞线程和解除阻塞线程,而且park()和unpark()不会遇到"Thread.suspend 和 Thread.resume所可能引发的死锁"问题. 因为park() 和 unpark()有许可的存在:调用 park() 的线程和另一个试图将其 unpark() 的线程之间的竞争将保持活性. 基本用法 LockSupport 很类似于二元信号

  • 使用java的HttpClient实现多线程并发

    说明:以下的代码基于httpclient4.5.2实现. 我们要使用java的HttpClient实现get请求抓取网页是一件比较容易实现的工作: public static String get(String url) { CloseableHttpResponseresponse = null; BufferedReader in = null; String result = ""; try { CloseableHttpClienthttpclient = HttpClient

  • Java多线程之异步Future机制的原理和实现

    项目中经常有些任务需要异步(提交到线程池中)去执行,而主线程往往需要知道异步执行产生的结果,这时我们要怎么做呢?用runnable是无法实现的,我们需要用callable看下面的代码: import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurren

  • java 线程创建多线程详解

    Java 线程类也是一个 object 类,它的实例都继承自 java.lang.Thread 或其子类. 可以用如下方式用 java 中创建一个线程,执行该线程可以调用该线程的 start()方法: Tread thread = new Thread(); thread.start(); 在上面的例子中,我们并没有为线程编写运行代码,因此调用该方法后线程就终止了. 编写线程运行时执行的代码有两种方式:一种是创建 Thread 子类的一个实例并重写 run 方法,第二种是创建类的时候实现 Run

  • Java线程的全方位详解

    目录 什么是线程? 线程的几种创建方式? 线程的几种状态? 线程相关的核心方法及作用? ❤️‍大家好,我是贾斯汀,今天主要聊一聊关于线程的瓜!❤️‍ 先来看一下线程这张图线程的几种运行状态之间运行流程: 看不懂没关系,慢慢来学习,往下学习来继续了解一下~ 什么是线程? 线程是进程的一部分,是程序执行中的一条执行路线: 进程就是指程序在其自身地址空间的一次执行活动,是程序独立运行的基本单位: 一个进程可以包含多条线程,一个条线程对应一个进程中的一条执行路线. 线程的几种创建方式? 主要由四种方式创

  • Java线程池 ThreadPoolExecutor 详解

    目录 一 为什么要使用线程池 二 线程池原理详解 2.1 线程池核心组成 2.2 Execute 原理 三 线程池的使用 3.1 创建线程池 3.1.1 自定义线程池 3.1.2 功能线程池 3.1.3 功能线程池存在的问题 3.2 向线程池提交任务 3.3 关闭线程池 3.4 自定义线程池需要考虑因素 一 为什么要使用线程池 对于操作系统而言,创建一个线程的代价是十分昂贵的, 需要给它分配内存.列入调度,同时在线程切换时要执行内存换页,清空 CPU 缓存,切换回来时还要重新从内存中读取信息,破

  • 基于Java回顾之多线程详解

    线程是操作系统运行的基本单位,它被封装在进程中,一个进程可以包含多个线程.即使我们不手动创造线程,进程也会有一个默认的线程在运行. 对于JVM来说,当我们编写一个单线程的程序去运行时,JVM中也是有至少两个线程在运行,一个是我们创建的程序,一个是垃圾回收. 线程基本信息 我们可以通过Thread.currentThread()方法获取当前线程的一些信息,并对其进行修改. 我们来看以下代码: 复制代码 代码如下: 查看并修改当前线程的属性 String name = Thread.currentT

  • Java 线程池ExecutorService详解及实例代码

    Java 线程池ExecutorService 1.线程池 1.1什么情况下使用线程池 单个任务处理的时间比较短. 将需处理的任务的数量大. 1.2使用线程池的好处 减少在创建和销毁线程上所花的时间以及系统资源的开销. 如果不使用线程池,有可能造成系统创建大量线程而导致消耗系统内存以及"过度切换"; 2.ExecutorService和Executors 2.1简介 ExecutorService是一个接口,继承了Executor, public interface ExecutorS

  • Java线程的控制详解

    1. join线程: 在线程执行过程中,有时想让另一个线程先执行,比如将一大问题分割成许多小问题,给每一个小问题分配线程,但所有小问题处理完后再让主线程进一步操作.此时我们可以在主线程中调用其它线程的join()方法,以阻塞调用线程(在这里为主线程). 示例代码: 复制代码 代码如下: package org.frzh.thread;    public class JoinThread extends Thread{      //提供一个有参构造器,用来设置线程的名字      public

  • java线程同步操作实例详解

    本文实例讲述了java线程同步操作.分享给大家供大家参考,具体如下: java线程同步 public class Hello { public static void main(String[] args) { MyRun myRun0 = new MyRun(); new Thread(myRun0, "Thread0").start(); new Thread(myRun0, "Thread1").start(); new Thread(myRun0, &quo

  • java线程优先级原理详解

    java 中的线程优先级的范围是1-10,默认的优先级是5.10最高. MIN_PRIORITY 1 MAX_PRIORITY 10 NORM_PRIORITY 5 优先级高的获得cpu的几率更大些,不是优先级高的就先执行完,线程优先级随机特性 在java中,线程的优先级具有继承性,例如A线程启动B线程,则A和B的优先级是一样的 线程创建后,可通过调用setPriority()方法改变优先级. public class Test5 { public static class TheadT ext

  • Java线程死锁代码详解

    /** * @author hollis */ public class JStackDemo { public static void main(String[] args) { Thread t1 = new Thread(new DeadLockclass(true));//建立一个线程 Thread t2 = new Thread(new DeadLockclass(false));//建立另一个线程 t1.start();//启动一个线程 t2.start();//启动另一个线程 }

  • Java ExecutorService四种线程池使用详解

    1.引言 合理利用线程池能够带来三个好处.第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗.第二:提高响应速度.当任务到达时,任务可以不需要的等到线程创建就能立即执行.第三:提高线程的可管理性.线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控.但是要做到合理的利用线程池,必须对其原理了如指掌. 2.线程池使用 Executors提供的四种线程 1.newCachedThreadPool创建一个可缓存线程池

随机推荐