一、概述
在Java中主要提供两种方式实现线程,分别为继承java.lang.Thread类与实现java.lang.Runnable接口。
二、继承Thread类
a、Thread类是java.lang包中的一个类,从这个类中实例化的对象代表线程,程序员启动一个新线程需要建立Thread类实例。
Thread类中常用的两个构造方法如下:
public Thread():创建一个新的线程对象。
public Thread(String threadName):创建一个名称为threadName的线程对象。
b、完成线程真正功能的代码放在类的run()方法中,当一个类继承Thread类后,就可以在该类中覆盖run()方法,将实现该线程功能的代码写入run()方法中,然后同时调用Thread类中的start()方法执行线程,也就是调用run()方法。
c、Thread对象需要一个任务来执行,任务是指线程在启动时执行的工作,该工作的功能代码被卸载run()方法总。
run()方法必须使用以下语法格式:
public void run(){
}
d、当执行一个线程程序时,就自动产生一个线程,主方法正式在这个线程上运行的。当不在启动其它线程是,该程序就是单线程程序,如在本章已签的程序都是单线程程序。主方法线程启动有java虚拟机负责,程序员负责启动自己的线程。
代码如下:
public static void main(String[] args){
new ThreadTest().start();
}
注意:(1)、如果start()方法调用一个已经启动的线程,系统将抛出IllegalThreadStateException异常。
(2)、在main方法中,使线程执行需要调用Thread类中的start()方法,strat()方法调用被覆盖的run()方法,如果不调用start()方法,线程永远都不会启动,在主方法没有调用start()方法之前,Thread对象只是一个实例,而不是一个真正的线程。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package com.lzw; 2 3 public class ThreadTest extends Thread { //指定继承Thread类 4 private int count = 10; 5 public void run() { //重写run()方法 6 while(true) { 7 System.out.print(count + " "); 8 if (--count == 0) { 9 return; 10 } 11 } 12 } 13 public static void main(String[] args) { 14 new ThreadTest().start(); 15 } 16 }
三、实现Runnable接口
有兴趣的读者可以查询API,从中可以发现,实质上Thread类实现了Runnable接口,其中的run()方法正式对Runnalble接口中的run()方法的具体实现。
a、实现Runnable接口的程序会创建一个Thread对象,并将Runnable对象与Thread对象相关联。
Thread对象有以下两个构造方法:
public Thread(Runnable target)
public Thread(Runnable target, String name)
这两个构造方法的参数中都存在Runnable实例,使用以上构造方法就可以将Runnable实例与Thread实例相关联。
b、使用Runnable接口启动新的线程步骤如下:
(1)、建立Runnable对象。
(2)、使用参数Runnable对象的构造方法创建Thread实例。
(3)、调用start()方法启动线程。
c、通过Runnable接口创建线程时程序员首先需要编写一个实现Runnable接口的类,然后实例化该类的对象这样就建立了Runnable对象;接下来使用相应的构造方法创建Thread实例;最后使用该实例调用Thread类中的start()方法启动线程。线程最引人注目的部分应该是与Swing相结合创建GUI程序,下面演示一个GUI程序,该程序实现了图标滚动的功能。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package com.lzw; 2 3 import java.awt.*; 4 import java.net.*; 5 6 import javax.swing.*; 7 8 public class SwingAndThread extends JFrame { 9 /** 10 * 11 */ 12 private static final long serialVersionUID = 1L; 13 private JLabel jl = new JLabel(); // 声明JLabel对象 14 private static Thread t; // 声明线程对象 15 private int count = 0; // 声明计数变量 16 private Container container = getContentPane(); // 声明容器 17 18 public SwingAndThread() { 19 setBounds(300, 200, 250, 100); // 绝对定位窗体大小与位置 20 container.setLayout(null); // 使窗体不使用任何布局管理器 21 URL url = SwingAndThread.class.getResource("/1.gif"); // 获取图片的URL 22 System.out.println(url); 23 Icon icon = new ImageIcon(url); // 实例化一个Icon 24 jl.setIcon(icon); // 将图标放置在标签中 25 // 设置图片在标签的最左方 26 jl.setHorizontalAlignment(SwingConstants.LEFT); 27 jl.setBounds(10, 10, 200, 50); // 设置标签的位置与大小 28 jl.setOpaque(true); 29 t = new Thread(new Runnable() { // 定义匿名内部类,该类实现Runnable接口 30 public void run() { // 重写run()方法 31 while (count <= 200) { // 设置循环条件 32 // 将标签的横坐标用变量表示 33 jl.setBounds(count, 10, 200, 50); 34 try { 35 Thread.sleep(1000); // 使线程休眠1000毫秒 36 } catch (Exception e) { 37 e.printStackTrace(); 38 } 39 count += 4; // 使横坐标每次增加4 40 if (count == 200) { 41 // 当图标到达标签的最右边,使其回到标签最左边 42 count = 10; 43 } 44 } 45 } 46 }); 47 t.start(); // 启动线程 48 container.add(jl); // 将标签添加到容器中 49 setVisible(true); // 使窗体可视 50 // 设置窗体的关闭方式 51 setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 52 } 53 54 public static void main(String[] args) { 55 new SwingAndThread(); // 实例化一个SwingAndThread对象 56 } 57 }