JAVA多线程机制之线程创建

在Java中创建线程有两种方式,一种是继承Thread,另一种是实现Runnable接口,Thread实际上也实现了Runnable接口。

Thread

构造方法

方法名 说明
Thread() 分配新的 Thread 对象
Thread(Runnable target) 分配新的 Thread 对象
Thread(Runnable target, String name) 分配新的 Thread 对象
Thread(String name) 分配新的 Thread 对象
Thread(ThreadGroup group, Runnable target) 分配新的 Thread 对象
Thread(ThreadGroup group, Runnable target, String name) 分配新的 Thread 对象,以便将 target 作为其运行对象,将指定的 name 作为其名称,并作为 group 所引用的线程组的一员
Thread(ThreadGroup group, Runnable target, String name, long stackSize) 分配新的 Thread 对象,以便将 target 作为其运行对象,将指定的 name 作为其名称,作为 group 所引用的线程组的一员,并具有指定的堆栈大小
Thread(ThreadGroup group, String name) 分配新的 Thread 对象

方法摘要

返回值 方法名 说明
static int activeCount() 返回当前线程的线程组中活动线程的数目
void checkAccess() 判定当前运行的线程是否有权修改该线程
static Thread currentThread() 返回对当前正在执行的线程对象的引用
static void dumpStack() 将当前线程的堆栈跟踪打印至标准错误流
static int enumerate(Thread[] tarray) 将当前线程的线程组及其子组中的每一个活动线程复制到指定的数组中
static Map<Thread,StackTraceElement[]> getAllStackTraces() 返回所有活动线程的堆栈跟踪的一个映射
ClassLoader getContextClassLoader() 返回该线程的上下文 ClassLoader
static Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() 返回线程由于未捕获到异常而突然终止时调用的默认处理程序
long getId() 返回该线程的标识符
String getName() 返回该线程的名称
int getPriority() 返回线程的优先级
StackTraceElement[] getStackTrace() 返回一个表示该线程堆栈转储的堆栈跟踪元素数组
Thread.State getState() 返回该线程的状态
ThreadGroup getThreadGroup() 返回该线程所属的线程组
Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() 返回该线程由于未捕获到异常而突然终止时调用的处理程序
static boolean holdsLock(Object obj) 当且仅当当前线程在指定的对象上保持监视器锁时,才返回 true
void interrupt() 中断线程
static boolean interrupted() 测试当前线程是否已经中断
boolean isAlive() 测试线程是否处于活动状态
boolean isDaemon() 测试该线程是否为守护线程
boolean isInterrupted() 测试线程是否已经中断
void join() 等待该线程终止
void join(long millis) 等待该线程终止的时间最长为 millis 毫秒
void join(long millis, int nanos) 等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒
void run() 如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回
void setContextClassLoader(ClassLoader cl) 设置该线程的上下文 ClassLoader
void setDaemon(boolean on) 将该线程标记为守护线程或用户线程
static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) 设置当线程由于未捕获到异常而突然终止,并且没有为该线程定义其他处理程序时所调用的默认处理程序
void setName(String name) 改变线程名称,使之与参数 name 相同
void setPriority(int newPriority) 更改线程的优先级
void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) 设置该线程由于未捕获到异常而突然终止时调用的处理程序
static void sleep(long millis) 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响
static void sleep(long millis, int nanos) 在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响
void start() 使该线程开始执行;Java 虚拟机调用该线程的 run 方法
String toString() 返回该线程的字符串表示形式,包括线程名称、优先级和线程组
static void yield() 暂停当前正在执行的线程对象,并执行其他线程

使用示例

public class ThreadDemo
{
   public static void main(String[] args)
   {
      PrintThread thread1 = new PrintThread();
      PrintThread thread2 = new PrintThread();
      // 通过start方法启动线程
      thread1.start();
      thread2.start();
   }
}

/**
 * 继承Thread
 * 
 * @author jianggujin
 * 
 */
class PrintThread extends Thread
{
   /**
    * 重写run方法,线程执行的逻辑写在该方法内
    */
   @Override
   public void run()
   {
      for (int i = 0; i < 10; i++)
      {
         try
         {
            // 使线程休眠100毫秒,使结果更直观
            Thread.sleep(100);
         }
         catch (InterruptedException e)
         {
            e.printStackTrace();
         }
         System.out.println(getName() + ":" + i);
      }
   }
}

运行结果如下:
Thread-1:0
Thread-0:0
Thread-0:1
Thread-1:1
Thread-0:2
Thread-1:2
Thread-0:3
Thread-1:3
Thread-0:4
Thread-1:4
Thread-1:5
Thread-0:5
Thread-1:6
Thread-0:6
Thread-0:7
Thread-1:7
Thread-0:8
Thread-1:8
Thread-1:9
Thread-0:9

在上面的示例中,我们使用了继承Thread的方式创建了线程对象并通过start()方法启动了线程,在例子中,我们启动了两个线程,线程只是简单的输出一句话,通过查看运行结果,我们可以发现两个线程是交错执行的。

Runnable

方法摘要

返回值 方法名 说明
void run() 使用实现接口 Runnable 的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用对象的 run 方法

使用示例

public class ThreadDemo
{
   public static void main(String[] args)
   {
      PrintThread thread1 = new PrintThread("Thread-0");
      PrintThread thread2 = new PrintThread("Thread-1");
      // 使用该种方式启动线程
      new Thread(thread1).start();
      new Thread(thread2).start();
   }
}

/**
 * 实现Runnable接口
 * 
 * @author jianggujin
 * 
 */
class PrintThread implements Runnable
{
   // 用于标识线程
   private String name;

   public PrintThread(String name)
   {
      this.name = name;
   }

   /**
    * 实现run方法,线程执行的逻辑写在该方法内
    */
   @Override
   public void run()
   {
      for (int i = 0; i < 10; i++)
      {
         try
         {
            // 使线程休眠100毫秒,使结果更直观
            Thread.sleep(100);
         }
         catch (InterruptedException e)
         {
            e.printStackTrace();
         }
         System.out.println(getName() + ":" + i);
      }
   }

   public String getName()
   {
      return name;
   }
}

运行结果:
Thread-0:0
Thread-1:0
Thread-1:1
Thread-0:1
Thread-0:2
Thread-1:2
Thread-0:3
Thread-1:3
Thread-0:4
Thread-1:4
Thread-1:5
Thread-0:5
Thread-0:6
Thread-1:6
Thread-0:7
Thread-1:7
Thread-0:8
Thread-1:8
Thread-1:9
Thread-0:9

join()

有的时候,我们希望当一个线程执行完后,在继续执行其他线程,比如一些初始化工作。这个时候我们可以使用join()方法,join()方法可以等待该线程终止。

使用示例

public class ThreadDemo
{
   public static void main(String[] args)
   {
      PrintThread thread1 = new PrintThread();
      PrintThread thread2 = new PrintThread();
      // 通过start方法启动线程
      thread1.start();
      try
      {
         //等待线程执行结束
         thread1.join();
      }
      catch (InterruptedException e)
      {
         e.printStackTrace();
      }
      thread2.start();
   }
}

/**
 * 继承Thread
 * 
 * @author jianggujin
 * 
 */
class PrintThread extends Thread
{
   /**
    * 重写run方法,线程执行的逻辑写在该方法内
    */
   @Override
   public void run()
   {
      for (int i = 0; i < 10; i++)
      {
         try
         {
            // 使线程休眠100毫秒,使结果更直观
            Thread.sleep(100);
         }
         catch (InterruptedException e)
         {
            e.printStackTrace();
         }
         System.out.println(getName() + ":" + i);
      }
   }
}

运行结果:
Thread-0:0
Thread-0:1
Thread-0:2
Thread-0:3
Thread-0:4
Thread-0:5
Thread-0:6
Thread-0:7
Thread-0:8
Thread-0:9
Thread-1:0
Thread-1:1
Thread-1:2
Thread-1:3
Thread-1:4
Thread-1:5
Thread-1:6
Thread-1:7
Thread-1:8
Thread-1:9

通过运行结果我们可以看到,当我们使用join方法后,会等待线程执行结束再继续执行另一个线程。

上一篇:[atARC134F]Flipping Coins


下一篇:归一化(softmax)、信息熵、交叉熵