如何创建和启动一个线程?

原文转自:http://www.tqcto.com/article/recommend/137.html

一、定义线程 
1、继承java.lang.Thread类。 
此类中有个run()方法,应该注意其用法: 
public void run()

如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。 
Thread 的子类应该重写该方法。

2、实现java.lang.Runnable接口。 
public  void run()

使用实现接口 Runnable 的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用对象的 run 方法。 
方法 run 的常规协定是,它可能执行任何所需的操作。

二、实例化线程

1、如果是扩展java.lang.Thread类的线程,则直接new即可。

2、如果是实现了java.lang.Runnable接口的类,则用Thread的构造方法:

Java代码

  1. Thread(Runnable target)
  2. Thread(Runnable target, String name)
  3. Thread(ThreadGroup group, Runnable target)
  4. Thread(ThreadGroup group, Runnable target, String name)
  5. Thread(ThreadGroup group, Runnable target, String name, long stackSize)

三、启动线程

在线程的Thread对象上调用start()方法,而不是run()或者别的方法。

在调用start()方法之前:线程处于新状态中,新状态指有一个Thread对象,但还没有一个真正的线程。

在调用start()方法之后:发生了一系列复杂的事情 
启动新的执行线程(具有新的调用栈); 
该线程从新状态转移到可运行状态; 
当该线程获得机会执行时,其目标run()方法将运行。

注意:对Java来说,run()方法没有任何特别之处。像main()方法一样,它只是新线程知道调用的方法名称(和签名)。因此,在Runnable上或者Thread上调用run方法是合法的。但并不启动新的线程。

四、例子

1、实现Runnable接口的多线程例子

Java代码

  1. /**
  2. * 实现Runnable接口的类
  3. *
  4. * @author leizhimin 2008-9-13 18:12:10
  5. */
  6. public class DoSomething implements Runnable {
  7. private String name;
  8. public DoSomething(String name) {
  9. this.name = name;
  10. }
  11. public void run() {
  12. for (int i = 0; i < 5; i++) {
  13. for (long k = 0; k < 100000000; k++) ;
  14. System.out.println(name + ": " + i);
  15. }
  16. }
  17. }
  18. /**
  19. * 测试Runnable类实现的多线程程序
  20. *
  21. * @author leizhimin 2008-9-13 18:15:02
  22. */
  23. public class TestRunnable {
  24. public static void main(String[] args) {
  25. DoSomething ds1 = new DoSomething("阿三");
  26. DoSomething ds2 = new DoSomething("李四");
  27. Thread t1 = new Thread(ds1);
  28. Thread t2 = new Thread(ds2);
  29. t1.start();
  30. t2.start();
  31. }
  32. }

执行结果: 
李四: 0 
阿三: 0 
李四: 1 
阿三: 1 
李四: 2 
李四: 3 
阿三: 2 
李四: 4 
阿三: 3 
阿三: 4

Process finished with exit code 0

2、扩展Thread类实现的多线程例子

Java代码

  1. /**
  2. * 测试扩展Thread类实现的多线程程序
  3. *
  4. * @author leizhimin 2008-9-13 18:22:13
  5. */
  6. public class TestThread extends Thread{
  7. public TestThread(String name) {
  8. super(name);
  9. }
  10. public void run() {
  11. for(int i = 0;i<5;i++){
  12. for(long k= 0; k <100000000;k++);
  13. System.out.println(this.getName()+" :"+i);
  14. }
  15. }
  16. public static void main(String[] args) {
  17. Thread t1 = new TestThread("阿三");
  18. Thread t2 = new TestThread("李四");
  19. t1.start();
  20. t2.start();
  21. }
  22. }

执行结果: 
阿三 :0 
李四 :0 
阿三 :1 
李四 :1 
阿三 :2 
李四 :2 
阿三 :3 
阿三 :4 
李四 :3 
李四 :4

Process finished with exit code 0

对于上面的多线程程序代码来说,输出的结果是不确定的。其中的一条语句for(long k= 0; k <100000000;k++);是用来模拟一个非常耗时的操作的。

五、一些常见问题

1、线程的名字,一个运行中的线程总是有名字的,名字有两个来源,一个是虚拟机自己给的名字,一个是你自己的定的名字。在没有指定线程名字的情况下,虚拟机总会为线程指定名字,并且主线程的名字总是mian,非主线程的名字不确定。 
2、线程都可以设置名字,也可以获取线程的名字,连主线程也不例外。 
3、获取当前线程的对象的方法是:Thread.currentThread(); 
4、在上面的代码中,只能保证:每个线程都将启动,每个线程都将运行直到完成。一系列线程以某种顺序启动并不意味着将按该顺序执行。对于任何一组启动的线程来说,调度程序不能保证其执行次序,持续时间也无法保证。 
5、当线程目标run()方法结束时该线程完成。 
6、一旦线程启动,它就永远不能再重新启动。只有一个新的线程可以被启动,并且只能一次。一个可运行的线程或死线程可以被重新启动。 
7、线程的调度是JVM的一部分,在一个CPU的机器上上,实际上一次只能运行一个线程。一次只有一个线程栈执行。JVM线程调度程序决定实际运行哪个处于可运行状态的线程。 
众多可运行线程中的某一个会被选中做为当前线程。可运行线程被选择运行的顺序是没有保障的。 
8、尽管通常采用队列形式,但这是没有保障的。队列形式是指当一个线程完成“一轮”时,它移到可运行队列的尾部等待,直到它最终排队到该队列的前端为止,它才能被再次选中。事实上,我们把它称为可运行池而不是一个可运行队列,目的是帮助认识线程并不都是以某种有保障的顺序排列唱呢个一个队列的事实。 
9、尽管我们没有无法控制线程调度程序,但可以通过别的方式来影响线程调度的方式。

原文转自:编程技术

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-01 18:46:52

如何创建和启动一个线程?的相关文章

如何定义,创建,启动一个线程

如何定义一个线程?第一通过继承java.lang.Thead类来定义一个线程.第二,通过实现java.lang.runnable接口定义一个线程. 为什么不采用run方法直接启动线程呢?线程是由操作系统来管理的,操作系统启动一个线程,会调用本地的一个代码,这个本地的代码会使系统初始化一个新的线程,由新的线程来启动Thead类中的run方法,所以要通过start方法来启动一个线程 两种定义线程的方式都有哪些优缺点?

启动一个线程是用run()还是start()

启动线程肯定要用start()方法.当用start()开始一个线程后,线程就进入就绪状态,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行.这并不意味着线程就会立即运行.当cpu分配给它时间时,才开始执行run()方法(如果有的话).start()是方法,它调用run()方法.而run()方法是你必须重写的. run()方法中包含的是线程的主体. 继承Thread类的启动方式: 1 public class ThreadStartTest { 2 public stati

从Xen Host Kernel复制出一个半虚拟化的Guest 创建并启动一个xen半虚拟化PV客户机

在< 创建并启动一个xen半虚拟化PV客户机 >一文中讲解了如何从Ubuntu的http源安装半虚拟化的xen guest OS,核心思想是先下载客户机的vmlinuz和initrd,启动xen虚拟机后将会选择ubuntu网络源,进行在线安装.后来准备做几个guest副本时,发现这种在逻辑卷中安装的guest好像难以复制(暂时不知道,主要是不知道如何mount这个逻辑卷,因为它又被分成了Linux和Swap格式),看如下图,该虚拟机使用的一个lv_domU2: 为了能够方便复制出多个半虚拟化g

weblogic管理2 - 创建并启动一个managed server

创建一个managed server. 1.  进入网页console管理页面,如:http://10.100.25.14:7001/console     , 先点击->服务器 (红色标记框),再点击->锁定并编辑  . 2.   点击-> 新建 3. 填好相关内容 (注意端口不要与admin server冲突) , 点击-> 下一步 4.  点击-> 完成 *********至此一个managed server已经创建完成. -----------------------

随着tomcat一起启动一个线程 (转)

原帖:http://blog.163.com/[email protected]/blog/static/1806962120124285346297/ 在Java web开发时如何在开启一个后台线程,随着Tomcat的启动而执行呢? 可以参考下面的步骤: 1.首先在工程中定义Class继承ServletContextListener接口,并定义线程和线程函数,实例如下代码: package test; import javax.servlet.*; public class MyCode im

JAVA线程池原理源码解析—为什么启动一个线程池,提交一个任务后,Main方法不会退出?

起因 public static void main(String[] args) { ExecutorService service = Executors.newFixedThreadPool(10); service.submit(() -> System.out.println("Hello ")); System.out.println("World"); } 呵呵,执行结果谁都知道,显而易见结论线程池的创建的时候,第一次submit操作会创建Wor

当多个客户请求一个servlet时,引擎为每个客户启动一个线程,那么servlet类的成员变量被所有的线程共享?

因为servlet的实现是单例,多线程也就是说,N个客户端请求同一个servlet,他们所请求的是同一个对象,成员变量是属于这个对象的,因此成员变量也被共享了因此在servlet编程中,无状态的servlet(就是不写属性,所以变量都在dopost或者doget里面)是线程安全的,否则,由于会共享到成员变量,因此就有可能不是线程安全的.

由一个成员函数来启动一个线程

/*shows how to start a thread based on a class memeber function using a static member function.*/ #define WIN32_LEAN_AND_MEAN #include<stdio.h> #include<stdlib.h> #include<Windows.h> #include<process.h> typedef unsigned(WINAPI *PBE

JAVA基础----应用程序中如何新开一个线程

通过继承Thread新开线程 将类声明为 Thread 的子类.该子类应重写 Thread 类的 run 方法.接下来可以分配并启动该子类的实例.例如,计算大于某一规定值的质数的线程可以写成: class PrimeThread extends Thread { long minPrime; PrimeThread(long minPrime) { this.minPrime = minPrime; } public void run() { // compute primes larger t