Java多线程初学者指南(2):用Thread类创建线程

简介: 本文为原创,如需转载,请注明作者和出处,谢谢!      在Java中创建线程有两种方法:使用Thread类和使用Runnable接口。在使用Runnable接口时需要建立一个Thread实例。

本文为原创,如需转载,请注明作者和出处,谢谢!

     Java中创建线程有两种方法:使用Thread类和使用Runnable接口。在使用Runnable接口时需要建立一个Thread实例。因此,无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例。Thread类的构造方法被重载了八次,构造方法如下:

public  Thread( );
public  Thread(Runnable target);
public  Thread(String name);
public  Thread(Runnable target, String name);
public  Thread(ThreadGroup group, Runnable target);
public  Thread(ThreadGroup group, String name);
public  Thread(ThreadGroup group, Runnable target, String name);
public  Thread(ThreadGroup group, Runnable target, String name,  long  stackSize);

Runnable target

实现了Runnable接口的类的实例。要注意的是Thread类也实现了Runnable接口,因此,从Thread类继承的类的实例也可以作为target传入这个构造方法。

String name

线程的名子。这个名子可以在建立Thread实例后通过Thread类的setName方法设置。如果不设置线程的名子,线程就使用默认的线程名:Thread-NN是线程建立的顺序,是一个不重复的正整数。

ThreadGroup group

当前建立的线程所属的线程组。如果不指定线程组,所有的线程都被加到一个默认的线程组中。关于线程组的细节将在后面的章节详细讨论。

long stackSize

    线程栈的大小,这个值一般是CPU页面的整数倍。如x86的页面大小是4KB。在x86平台下,默认的线程栈大小是12KB

一个普通的Java类只要从Thread类继承,就可以成为一个线程类。并可通过Thread类的start方法来执行线程代码。虽然Thread类的子类可以直接实例化,但在子类中必须要覆盖Thread类的run方法才能真正运行线程的代码。下面的代码给出了一个使用Thread类建立线程的例子:

   001    package  mythread;
  
002   
  
003    public   class  Thread1  extends  Thread
  
004   {
  
005        public   void  run()
  
006       {
  
007           System.out.println( this .getName());
  
008       }
  
009        public   static   void  main(String[] args)
  
010       {
  
011           System.out.println(Thread.currentThread().getName());
  
012           Thread1 thread1  =   new  Thread1();
  
013           Thread1 thread2  =   new  Thread1 ();
  
014           thread1.start();
  
015           thread2.start();
  
016       }
  
017   }


     上面的代码建立了两个线程:thread1和thread2。上述代码中的005至008行是Thread1类的run方法。当在014和015行调用 start方法时,系统会自动调用run方法。在007行使用this.getName()输出了当前线程的名字,由于在建立线程时并未指定线程名,因 此,所输出的线程名是系统的默认值,也就是Thread-n的形式。在011行输出了主线程的线程名。
    上面代码的运行结果如下:

main
Thread-
0
Thread-
1

 

从上面的输出结果可以看出,第一行输出的main是主线程的名子。后面的Thread-1Thread-2分别是thread1thread2的输出结果。

注意:任何一个Java程序都必须有一个主线程。一般这个主线程的名子为main。只有在程序中建立另外的线程,才能算是真正的多线程程序。也就是说,多线程程序必须拥有一个以上的线程。
    Thread类有一个重载构造方法可以设置线程名。除了使用构造方法在建立线程时设置线程名,还可以使用Thread类的setName方法修改线程名。要想通过Thread类的构造方法来设置线程名,必须在Thread的子类中使用Thread类的public Thread(String name)构造方法,因此,必须在Thread的子类中也添加一个用于传入线程名的构造方法。下面的代码给出了一个设置线程名的例子:

   001    package  mythread;
  
002   
  
003    public   class  Thread2  extends  Thread
  
004   {
  
005        private  String who;
  
006   
  
007        public   void  run()
  
008       {
  
009           System.out.println(who  +   " : "   +   this .getName());
  
010       }
  
011        public  Thread2(String who)
  
012       {
  
013            super ();
  
014            this .who  =  who;
  
015       }
  
016        public  Thread2(String who, String name)
  
017       {
  
018            super (name);
  
019            this .who  =  who;
  
020       }
  
021        public   static   void  main(String[] args)
  
022       {
  
023           Thread2 thread1  =   new  Thread2 ( " thread1 " " MyThread1 " );
  
024           Thread2 thread2  =   new  Thread2 ( " thread2 " );
  
025           Thread2 thread3  =   new  Thread2 ( " thread3 " );
  
026           thread2.setName( " MyThread2 " );
  
027           thread1.start();
  
028           thread2.start();
  
029           thread3.start();
  
030       }
  
031   

 

在类中有两个构造方法:

011行:public sample2_2(String who)

这个构造方法有一个参数:who。这个参数用来标识当前建立的线程。在这个构造方法中仍然调用Thread的默认构造方法public Thread( )

016行:public sample2_2(String who, String name)

这个构造方法中的who和第一个构造方法的who的含义一样,而name参数就是线程的名名。在这个构造方法中调用了Thread类的public Thread(String name)构造方法,也就是第018行的super(name)

main方法中建立了三个线程:thread1thread2thread3。其中thread1通过构造方法来设置线程名,thread2通过setName方法来修改线程名,thread3未设置线程名。

    运行结果如下:

thread1:MyThread1
thread2:MyThread2
thread3:Thread-
1

 

从上面的输出结果可以看出,thread1thread2的线程名都已经修改了,而thread3的线程名仍然为默认值:Thread-1thread3的线程名之所以不是Thread-2,而是Thread-1,这是因为在026已经指定了thread2的Name,因此,启动thread3时就将thread3的线程名设为Thread-1因此就会得到上面的输出结果。

注意:在调用start方法前后都可以使用setName设置线程名,但在调用start方法后使用setName修改线程名,会产生不确定性,也就是说可能在run方法执行完后才会执行setName。如果在run方法中要使用线程名,就会出现虽然调用了setName方法,但线程名却未修改的现象。

Thread 类的 start 方法不能多次调用,如不能调用两次 thread1.start() 方法。否则会抛出一个 IllegalThreadStateException 异常。
目录
打赏
0
0
0
0
11
分享
相关文章
|
2月前
|
python3多线程中使用线程睡眠
本文详细介绍了Python3多线程编程中使用线程睡眠的基本方法和应用场景。通过 `time.sleep()`函数,可以使线程暂停执行一段指定的时间,从而控制线程的执行节奏。通过实际示例演示了如何在多线程中使用线程睡眠来实现计数器和下载器功能。希望本文能帮助您更好地理解和应用Python多线程编程,提高程序的并发能力和执行效率。
86 20
Unity多线程使用(线程池)
在C#中使用线程池需引用`System.Threading`。创建单个线程时,务必在Unity程序停止前关闭线程(如使用`Thread.Abort()`),否则可能导致崩溃。示例代码展示了如何创建和管理线程,确保在线程中执行任务并在主线程中处理结果。完整代码包括线程池队列、主线程检查及线程安全的操作队列管理,确保多线程操作的稳定性和安全性。
|
4月前
|
单线程传奇Redis,为何引入多线程?
Redis 4.0 引入多线程支持,主要用于后台对象删除、处理阻塞命令和网络 I/O 等操作,以提高并发性和性能。尽管如此,Redis 仍保留单线程执行模型处理客户端请求,确保高效性和简单性。多线程仅用于优化后台任务,如异步删除过期对象和分担读写操作,从而提升整体性能。
104 1
|
4月前
|
【JavaEE】——多线程常用类
Callable的call方法,FutureTask类,ReentrantLock可重入锁和对比,Semaphore信号量(PV操作)CountDownLatch锁存器,
【JavaEE】线程创建和终止,Thread类方法,变量捕获(7000字长文)
创建线程的五种方式,Thread常见方法(守护进程.setDaemon() ,isAlive),start和run方法的区别,如何提前终止一个线程,标志位,isinterrupted,变量捕获
【JavaEE】多线程编程引入——认识Thread类
Thread类,Thread中的run方法,在编程中怎么调度多线程
|
2月前
|
Linux编程: 在业务线程中注册和处理Linux信号
本文详细介绍了如何在Linux中通过在业务线程中注册和处理信号。我们讨论了信号的基本概念,并通过完整的代码示例展示了在业务线程中注册和处理信号的方法。通过正确地使用信号处理机制,可以提高程序的健壮性和响应能力。希望本文能帮助您更好地理解和应用Linux信号处理,提高开发效率和代码质量。
69 17
|
2月前
|
Linux编程: 在业务线程中注册和处理Linux信号
通过本文,您可以了解如何在业务线程中注册和处理Linux信号。正确处理信号可以提高程序的健壮性和稳定性。希望这些内容能帮助您更好地理解和应用Linux信号处理机制。
68 26
|
4月前
|
Java多线程编程秘籍:各种方案一网打尽,不要错过!
Java 中实现多线程的方式主要有四种:继承 Thread 类、实现 Runnable 接口、实现 Callable 接口和使用线程池。每种方式各有优缺点,适用于不同的场景。继承 Thread 类最简单,实现 Runnable 接口更灵活,Callable 接口支持返回结果,线程池则便于管理和复用线程。实际应用中可根据需求选择合适的方式。此外,还介绍了多线程相关的常见面试问题及答案,涵盖线程概念、线程安全、线程池等知识点。
385 2
Java多线程编程的陷阱与解决方案####
本文深入探讨了Java多线程编程中常见的问题及其解决策略。通过分析竞态条件、死锁、活锁等典型场景,并结合代码示例和实用技巧,帮助开发者有效避免这些陷阱,提升并发程序的稳定性和性能。 ####

热门文章

最新文章

下一篇
oss创建bucket
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等