线程 - Java 多线程编程(下)

简介: 线程 - Java 多线程编程(下)

Thread 方法

下表列出了Thread类的一些重要方法:

序号 方法描述
1 public void start()
使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
2 public void run()
如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。
3 public final void setName(String name)
改变线程名称,使之与参数 name 相同。
4 public final void setPriority(int priority)
更改线程的优先级。
5 public final void setDaemon(boolean on)
将该线程标记为守护线程或用户线程。
6 public final void join(long millisec)
等待该线程终止的时间最长为 millis 毫秒。
7 public void interrupt()
中断线程。
8 public final boolean isAlive()
测试线程是否处于活动状态。

测试线程是否处于活动状态。 上述方法是被Thread对象调用的。下面的方法是Thread类的静态方法。

序号 方法描述
1 public static void yield()
暂停当前正在执行的线程对象,并执行其他线程。
2 public static void sleep(long millisec)
在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。
3 public static boolean holdsLock(Object x)
当且仅当当前线程在指定的对象上保持监视器锁时,才返回 true。
4 public static Thread currentThread()
返回对当前正在执行的线程对象的引用。
5

public static void dumpStack()

将当前线程的堆栈跟踪打印至标准错误流。

实例

如下的ThreadClassDemo 程序演示了Thread类的一些方法:

DisplayMessage.java 文件代码:

// 文件名 : DisplayMessage.java// 通过实现 Runnable 接口创建线程publicclassDisplayMessageimplementsRunnable {
privateStringmessage;
publicDisplayMessage(Stringmessage) {
this.message=message;
   }
publicvoidrun() {
while(true) {
System.out.println(message);
      }
   }
}

GuessANumber.java 文件代码:

// 文件名 : GuessANumber.java// 通过继承 Thread 类创建线程publicclassGuessANumberextendsThread {
privateintnumber;
publicGuessANumber(intnumber) {
this.number=number;
   }
publicvoidrun() {
intcounter=0;
intguess=0;
do {
guess= (int) (Math.random() *100+1);
System.out.println(this.getName() +" guesses "+guess);
counter++;
      } while(guess!=number);
System.out.println("** Correct!"+this.getName() +"in"+counter+"guesses.**");
   }
}

ThreadClassDemo.java 文件代码:

// 文件名 : ThreadClassDemo.javapublicclassThreadClassDemo {
publicstaticvoidmain(String [] args) {
Runnablehello=newDisplayMessage("Hello");
Threadthread1=newThread(hello);
thread1.setDaemon(true);
thread1.setName("hello");
System.out.println("Starting hello thread...");
thread1.start();
Runnablebye=newDisplayMessage("Goodbye");
Threadthread2=newThread(bye);
thread2.setPriority(Thread.MIN_PRIORITY);
thread2.setDaemon(true);
System.out.println("Starting goodbye thread...");
thread2.start();
System.out.println("Starting thread3...");
Threadthread3=newGuessANumber(27);
thread3.start();
try {
thread3.join();
      }catch(InterruptedExceptione) {
System.out.println("Thread interrupted.");
      }
System.out.println("Starting thread4...");
Threadthread4=newGuessANumber(75);
thread4.start();
System.out.println("main() is ending...");
   }
}

运行结果如下,每一次运行的结果都不一样。

Starting hello thread...

Starting goodbye thread...

Hello

Hello

Hello

Hello

Hello

Hello

Goodbye

Goodbye

Goodbye

Goodbye

Goodbye

.......


通过 Callable 和 Future 创建线程

  • 1. 创建 Callable 接口的实现类,并实现 call() 方法,该 call() 方法将作为线程执行体,并且有返回值。
  • 2. 创建 Callable 实现类的实例,使用 FutureTask 类来包装 Callable 对象,该 FutureTask 对象封装了该 Callable 对象的 call() 方法的返回值。
  • 3. 使用 FutureTask 对象作为 Thread 对象的 target 创建并启动新线程。
  • 4. 调用 FutureTask 对象的 get() 方法来获得子线程执行结束后的返回值。
publicclassCallableThreadTestimplementsCallable<Integer> {
publicstaticvoidmain(String[] args)  
    {  
CallableThreadTestctt=newCallableThreadTest();  
FutureTask<Integer>ft=newFutureTask<>(ctt);  
for(inti=0;i<100;i++)  
        {  
System.out.println(Thread.currentThread().getName()+" 的循环变量i的值"+i);  
if(i==20)  
            {  
newThread(ft,"有返回值的线程").start();  
            }  
        }  
try        {  
System.out.println("子线程的返回值:"+ft.get());  
        } catch (InterruptedExceptione)  
        {  
e.printStackTrace();  
        } catch (ExecutionExceptione)  
        {  
e.printStackTrace();  
        }  
    }
@OverridepublicIntegercall() throwsException    {  
inti=0;  
for(;i<100;i++)  
        {  
System.out.println(Thread.currentThread().getName()+" "+i);  
        }  
returni;  
    }  
}

创建线程的三种方式的对比

  • 1. 采用实现 Runnable、Callable 接口的方式创建多线程时,线程类只是实现了 Runnable 接口或 Callable 接口,还可以继承其他类。
  • 2. 使用继承 Thread 类的方式创建多线程时,编写简单,如果需要访问当前线程,则无需使用 Thread.currentThread() 方法,直接使用 this 即可获得当前线程。

线程的几个主要概念

在多线程编程时,你需要了解以下几个概念:

  • 线程同步
  • 线程间通信
  • 线程死锁
  • 线程控制:挂起、停止和恢复

多线程的使用

有效利用多线程的关键是理解程序是并发执行而不是串行执行的。例如:程序中有两个子系统需要并发执行,这时候就需要利用多线程编程。

通过对多线程的使用,可以编写出非常高效的程序。不过请注意,如果你创建太多的线程,程序执行的效率实际上是降低了,而不是提升了。

请记住,上下文的切换开销也很重要,如果你创建了太多的线程,CPU 花费在上下文的切换的时间将多于执行程序的时间!

目录
相关文章
|
12小时前
|
缓存 Java
【JAVA进阶篇教学】第五篇:Java多线程编程
【JAVA进阶篇教学】第五篇:Java多线程编程
|
1天前
|
Java
【Java多线程】面试常考 —— JUC(java.util.concurrent) 的常见类
【Java多线程】面试常考 —— JUC(java.util.concurrent) 的常见类
9 0
|
1天前
|
设计模式 消息中间件 安全
【Java多线程】关于多线程的一些案例 —— 单例模式中的饿汉模式和懒汉模式以及阻塞队列
【Java多线程】关于多线程的一些案例 —— 单例模式中的饿汉模式和懒汉模式以及阻塞队列
8 0
|
1天前
|
安全 Java 程序员
【Java多线程】面试常考——锁策略、synchronized的锁升级优化过程以及CAS(Compare and swap)
【Java多线程】面试常考——锁策略、synchronized的锁升级优化过程以及CAS(Compare and swap)
5 0
|
1天前
|
Java 数据库
【Java多线程】对线程池的理解并模拟实现线程池
【Java多线程】对线程池的理解并模拟实现线程池
9 1
|
1天前
|
Java
【Java多线程】分析线程加锁导致的死锁问题以及解决方案
【Java多线程】分析线程加锁导致的死锁问题以及解决方案
9 1
|
1天前
|
存储 缓存 安全
【Java多线程】线程安全问题与解决方案
【Java多线程】线程安全问题与解决方案
8 1
|
1天前
|
Java 调度
【Java多线程】线程中几个常见的属性以及状态
【Java多线程】线程中几个常见的属性以及状态
7 0
|
15天前
|
监控 Java 调度
Java多线程实战-从零手搓一个简易线程池(四)线程池生命周期状态流转实现
Java多线程实战-从零手搓一个简易线程池(四)线程池生命周期状态流转实现
|
15天前
|
设计模式 Java
Java多线程实战-从零手搓一个简易线程池(三)线程工厂,核心线程与非核心线程逻辑实现
Java多线程实战-从零手搓一个简易线程池(三)线程工厂,核心线程与非核心线程逻辑实现