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(newMyRunnable());

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 = newThread(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多线程的创建方法的更多相关文章

  1. Java多线程(1) 创建

    一.线程的生命周期及五种基本状态 关于Java中线程的生命周期,首先看一下以下这张较为经典的图: Java线程具有五中基本状态 新建状态(New):当线程对象对创建后,即进入了新建状态,如:Threa ...

  2. Win32 多线程的创建方法和基本使用

    Win32多线程的创建方法主要有: (1)CreateThread() (2)_beginthread()&&_beginthreadex() (3)AfxBeginThread() ...

  3. java多线程-概念&创建启动&中断&守护线程&优先级&线程状态(多线程编程之一)

    今天开始就来总结一下Java多线程的基础知识点,下面是本篇的主要内容(大部分知识点参考java核心技术卷1): 1.什么是线程以及多线程与进程的区别 2.多线程的创建与启动 3.中断线程和守护线程以及 ...

  4. Java多线程的创建(一)

    方法一:继承Thread类实现 1.创建一个类A,并继承Thread类 2.重写A的run()方法 3.创建A的实例对象b,即创建了线程对象 4.使用b调用start()方法:启动线程(会自动调用ru ...

  5. Java多线程——之一创建线程的四种方法

    1.实现Runnable接口,重载run(),无返回值 package thread; public class ThreadRunnable implements Runnable { public ...

  6. Java多线程同步的方法

    一 synchronized关键字 1.synchronized实现原理: ---基于对象监视器(锁) java中所有对象都自动含有单一的锁,JVM负责跟踪对象被加锁的次数.如果一个对象被解锁,其计数 ...

  7. Java多线程的创建与简单使用

    一.线程的基本概念 什么是线程:Thread 进程内部的一个执行单元,它是程序中一个单一的顺序控制流程. 线程又被称为轻量级进程(lightweight process) 如果在一个进程中同时运行了多 ...

  8. java多线程之创建线程的4种方式及Future

    Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例.Java可以用四种方式来创建线程: 继承Thread创建线程 实现Runnable接口创建线程 实现callab ...

  9. Java多线程的创建(二)

    前言: 虽然java的API中说创建多线程的方式只有两种(There are two ways to create a new thread of execution),分别是继承Thread类创建和 ...

随机推荐

  1. Ubuntu16.04安装NVIDIA驱动、实现GPU加速

    NVIDIA驱动前前后后装了好几遍,下面把个人的经验分享下,大家仅供参考. 老规矩,先引用师兄的(最详细)https://blog.csdn.net/sinat_23853639/article/de ...

  2. USACO1.5 Mother's Milk【搜索】

    题目传送门 这道题还记得是我当年学广搜的时候做过. 如今再做,做了一个$dfs$版本的,比较简单,直接搞就可以了. 广搜的话,用结构体保存,然后塞到$queue$里面就可以了. /* ID: Star ...

  3. 【Linux 网络编程】滑动窗口协议

    <1>通知接受窗口(rwnd): 预防应用程序发送的数据超过对方的缓冲区.接收方使用的流量控制<2>拥塞窗口(cwnd): 预防应用程序发送的数据超过网络所承受的能力.发送方使 ...

  4. Objective-C中的自动释放池

    自动释放池块@autoreleasepool 自动释放池块在MRC和ARC下都可以使用.在MARC下,为了将自动释放池块内部的变量放入自动释放池,需要手动调用autorelease方法:在ARC下,只 ...

  5. linux-查询某软件的安装的目录

    eg:jenkins\\\ rpm -ql jenkins 安装目录/var/lib/jenkins 配置文件 /etc/sysconfig/jenkins 日志目录 /var/log/jenkins ...

  6. python面向对象中的封装、继承、多态

    封装 可以简单的理解为隐藏一切可以隐藏的实现细节,只向外界提供简单的编程接口.我们在类中定义的方法其实就是把数据和数据的操作封装起来了,在我们创建了对象之后,只需要给对象发送一个消息(调用方法)就可以 ...

  7. HDU-4717 The Moving Points(凸函数求极值)

    The Moving Points Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  8. list 小练习

    li = ["alex", "WuSir", "ritian", "barry", "wenzhou" ...

  9. KL散度的理解(GAN网络的优化)

    原文地址Count Bayesie 这篇文章是博客Count Bayesie上的文章Kullback-Leibler Divergence Explained 的学习笔记,原文对 KL散度 的概念诠释 ...

  10. 优化 Karatsuba 乘法(老物)

    虽然写好了我自己用的a*启发函数但还是有些不尽人意,如果通过数学分析确定不出问题可以工作了的话应该就会发出来了 // Karatsuba 递归式距离推导 // h(x) = f(x) * g(x):/ ...