2.1 什么是线程(What Is a Thread? )


举个栗子


public class HelloYB {
    public static void main(String[] args) {
        System.out.println("hello yellowbaby");
    }
}


一个很简单的程序是吧~我们的程序里面都是由一条条的指令(instructions)构成的,这个程序里面只有一个指令,打印~当然,你的程序不可能就这一条指令..,但是原理是一样的,这些指令的执行路径就是一个线程。(The execution path of these instructions is a thread)


多线程的魅力就在于享数据多线程程序共享的是整个java堆,数据能够透明的被存在堆中的对象共享,当然每个线程也都有自己的本地存储空间(threads can transparently share access between any object in the heap,Eachthread still has its own space for local variables )


212914833.gif

2.2 线程的创建(Creating a Thread)


书中的程序过于繁琐以及涉及了很多java swing的东西,我改编了一下,下面是个简略版,带有了创建线程的两个方式


package com.yellow.chapteOne;
/**
 *  第一种方式,直接继承 Thread 类 重写 run 方法
 * @author yellowbaby
 *
 */
public class MyTread extends Thread{
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
    @Override
    public void run() {
        new SwingTypeTester().show();
    }
    public static void main(String[] args) {
        new MyTread().start();
    }
}


这里是创建线程的第一种方式,直接继承 Thread ,重写 run 方法,当主线程调用 start方法的时候会执行 run 方法


package com.yellow.chapteOne;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class SwingTypeTester extends JFrame {
    private JButton quitButton;//退出按钮
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
    private JButton startButton;//开始按钮
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
    private MyJLabel displayBorad;//数字显示的面板
    public SwingTypeTester() {
        init();
    }
    private void init() {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
        JPanel p = new JPanel();
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
        startButton = new JButton("start");
        quitButton = new JButton("quit");
        displayBorad = new MyJLabel("0");
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
        p.add(startButton);
        p.add(quitButton);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
        add(p, BorderLayout.SOUTH);
        add(displayBorad,BorderLayout.NORTH);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
        startButton.addActionListener(new ActionListener() {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
            @Override
            public void actionPerformed(ActionEvent e) {//点击开始按钮后启动另一个线程
                Thread thread = new Thread(displayBorad);
                thread.start();
            }
        });
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
        quitButton.addActionListener(new ActionListener() {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
        pack();
    }
}


这是一个JFrame,有三个部件,两个button,一个Jlabel,点击按钮后我希望可以改变JLabel的值


package com.yellow.chapteOne;
import java.util.Random;
import javax.swing.JLabel;
/**
 * 创建线程的第二种方式,实现Runnable接口,然后传入Thread类里面执行
 * @author yellowbaby
 *
 */
public class MyJLabel extends JLabel implements Runnable{
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
    private static Random random = new Random();
    public MyJLabel(String string) {
        super(string);
    }
    @Override
    public void run() {
        while (true) {
            setText(String.valueOf(random.nextInt()));
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
    }
}

程序里面我一共创建了两枚线程,一枚是直接继承的Thread(用来启动界面),一枚是继承runnable接口(点击按钮后为了改变JLabel的值的),两种方式的优劣后面应该有详细的解释


2.3 线程的生命周期(The Lifecycle of a Thread)


1)线程的创建 (Creating a Thread)

一个Thread的实例就代表了一个线程,我们创建一个Thread的实例很明显就需要调用它的构造方法啦~让我们来瞄一眼它有哪些构造方法


public Thread() {//这是空的
    init(null, null, "Thread-" + nextThreadNum(), 0);
    }


public Thread(Runnable target) {//耳熟能详的接受一个runnable任务
    init(null, target, "Thread-" + nextThreadNum(), 0);
    }


public Thread(ThreadGroup group, String name) {//我们可以设置名称,但是这个ThreadGroup 是干啥的捏?
    init(group, null, name, 0);
    }


我搜了一下这个ThreadGroup 顿时涨姿势了有没有


先看注释


/**
 * A thread group represents a set of threads. In addition, a thread
 * group can also include other thread groups. The thread groups form
 * a tree in which every thread group except the initial thread group
 * has a parent. (这是一个树形结构哟,而且除了根节点...都有父节点)
 * <p>
 * A thread is allowed to access information about its own thread
 * group, but not to access information about its thread group's
 * parent thread group or any other thread groups.
 *
 * @author  unascribed
 * @version 1.66, 03/13/08
 * @since   JDK1.0
 */
public
class ThreadGroup implements Thread.UncaughtExceptionHandler


然后给你们看个小例子


public class AllThread {
    public static Thread[] getAllThread() {
        ThreadGroup root = Thread.currentThread().getThreadGroup();//得到当前线程所在的ThreadGroup
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
        ThreadGroup ttg = root;//因为ThreadGroups是树形结构的嘛,所以我们希望找到根节点是神马
        while ((ttg = ttg.getParent()) != null)
            root = ttg;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
        Thread[] tlist = new Thread[(int) (root.activeCount() * 1.2)];//目测一下大概有多少个线程,至于这个系数为毛是1.2,我应该和树形数学知识有关系.....
        return java.util.Arrays.copyOf(tlist, root.enumerate(tlist, true));
    }
    public static void main(String[] args) {
        Thread[] ts = getAllThread();
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
        for (Thread t : ts) {//这样我们就可以知道所有在跑的线程的所有信息,还可以进行一些操作比如设置priority神马的
            System.out.println(t.getId() + ": " + t.getName() + " "
                    + t.getPriority() + " " + t.getThreadGroup() + " ");
        }
    }
}


这是打印结果,我们的一共跑了5个线程,好吧我已经忍不住去研究这5个线程的细节了


2: Reference Handler 10 java.lang.ThreadGroup[name=system,maxpri=10]

3: Finalizer 8 java.lang.ThreadGroup[name=system,maxpri=10]

4: Signal Dispatcher 9 java.lang.ThreadGroup[name=system,maxpri=10]

5: Attach Listener 5 java.lang.ThreadGroup[name=system,maxpri=10]

1: main 5 java.lang.ThreadGroup[name=main,maxpri=10]


Reference Handler JVM在创建main线程后就创建Reference Handler线程,其优先级最高,为10,它主要用于处理引用对象本身(软引用、弱引用、虚引用)的垃圾回收问题。


Finalizer 这个线程也是在main线程之后创建的,其优先级为10,主要用于在垃圾收集前,调用对象的finalize()方法;


关于Finalizer线程的几点:

1)只有当开始一轮垃圾收集时,才会开始调用finalize()方法;因此并不是所有对象的finalize()方法都会被执行;

2)该线程也是daemon线程,因此如果虚拟机中没有其他非daemon线程,不管该线程有没有执行完finalize()方法,JVM也会退出;

3) JVM在垃圾收集时会将失去引用的对象包装成Finalizer对象(Reference的实现),并放入ReferenceQueue,由Finalizer线程来处理;最后将该Finalizer对象的引用置为null,由垃圾收集器来回收;4) JVM为什么要单独用一个线程来执行finalize()方法呢?如果JVM的垃圾收集线程自己来做,很有可能由于在finalize()方法中误操作导致GC线程停止或不可控,这对GC线程来说是一种灾难;


Attach Listener

Attach Listener线程是负责接收到外部的命令,而对该命令进行执行的并且吧结果返回给发送者。通常我们会用一些命令去要求jvm给我们一些反馈信息,如:java -version、jmap、jstack等等。如果该线程在jvm启动的时候没有初始化,那么,则会在用户第一次执行jvm命令时,得到启动。


Signal Dispatcher

前面我们提到Attach Listener线程的职责是接收外部jvm命令,当命令接收成功后,会交给signal dispather线程去进行分发到各个不同的模块处理命令,并且返回处理结果。signal dispather线程也是在第一次接收外部jvm命令时,进行初始化工作。


2.3.2 开始一个线程(Starting a Thread)

一个线程从被构造就已经存在了,但是没有执行任何代码,这个时候它处于一种等待状态,我们可以设置它的一些参数比如priority,name,daemon statue


当线程已经准备就绪,就可以调用start()方法了,这个方法最终会调用 run()方法,当start方法执行后,有两个线程在并行执行


当线程执行start后,这个线程就可以说是激活(alive)的了,我们可以用isAlive()来检测是否处于激活状态,如果返回是true,说明线程已经启动,并且在执行run方法了,如果返回的是false,说明还没有start或者已经结束了


看个例子说明 isAlive()方法


package com.yellow.chapteOne;
public class Test {
    public static void main(String args[]) throws InterruptedException {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
        Thread thread = new Thread(new Runnable() {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
            @Override
            public void run() {
                System.out.println("执行中");
            }
        });
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
        System.out.println(thread.isAlive());//执行前 false
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
        thread.start();
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
        System.out.println(thread.isAlive());//执行的时候 true
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
        thread.join();//等待线程结束
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
        System.out.println(thread.isAlive());//结束后false
    }
}


2.3.3 终止线程(Terminating a Thread)

正常情况,想要一个线程终止就是执行完run方法,还有办法就是抛出异常.....(run方法不能抛出check异常,但是能抛出unchecked异常),后面有两种终止线程的方式

2.3.4 线程暂停,挂起,恢复(Pausing, Suspending, and Resuming Threads)

我们熟悉能够暂停线程的方法就是sleep啦,但是sleep方法不算严格意义的thread suspension,真正的thread suspension是可以suspend其他线程以及resume其他线程的,而sleep方法只能对当前线程有用,真正意义的线程Suspending和Resuming的实现是用wait和notify方法,第三章里面会有详细说明

2.3.5 线程清除(Thread Cleanup)

既然线程也是一个对象,自然也会被垃圾收集器(garbage collect)管理,一般来说,当我们不再占用这个线程的引用的时候,这个thread就可以被回收了

一个继续持有引用的理由是我们的run方法还在继续执行,我们可以用isAlive方法来判断是否run还在执行,如果我们想强制等待某个线程执行完,可以使用join方法


具体扯扯join的用法,join的作用是等待一个线程挂掉!!


/**
    * Waits for this thread to die.
    *
    * @exception  InterruptedException if any thread has interrupted
    *             the current thread.  The <i>interrupted status</i> of the
    *             current thread is cleared when this exception is thrown.
    */
   public final void join() throws InterruptedException


看一个实例,我们吃饭前一定要洗手哦,一个吃饭线程,一个洗手线程,我们要求执行吃饭前洗手线程必须已经完成了,用join再合适不过了


package com.yellow.chapteOne;
public class Test {
    public static void main(String args[]) throws InterruptedException {
        final Thread washHandThread = new Thread(new Runnable() {//洗手线程
            @Override
            public void run() {
                System.out.println("吃饭前要洗手哟~");
            }
        });
        Thread eatThread = new Thread(new Runnable() {//吃饭线程
            @Override
            public void run() {
                isWashFinished();
                                                                                                                                                                                                                                                                                                                                                  
                try {
                    washHandThread.join();// 当eat线程到这里时候会被阻塞,为了等待wash线程完成才会继续执行
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                                                                                                                                                                                                                                                                                                                                                  
                isWashFinished();
                System.out.println("可以吃饭了");
            }
                                                                                                                                                                                                                                                                                                                                              
            /**
             * 如果洗手线程isAlive返回的true,说明洗手还没有完成,如果返回false,说明已经执行完了
             */
            public void isWashFinished() {
                if (washHandThread.isAlive()) {
                    System.out.println("还没有洗完呢");
                } else {
                    System.out.println("洗完了");
                }
            }
        });
        eatThread.start();
        washHandThread.start();
    }
}



说明,当一个线程执行其他线程的join的时候,会一直被阻塞直到那个线程的run方法执行完毕,如果在那之前run方法以及执行完了,join方法会立刻返回

(但是你千万不能用join方法去判断run方法是否已经执行完,你应该用isAlive方法)



下面补充一下线程的状态:


一个线程的各种状态为:


170336301.gif


1)新生态(newly created),刚刚被new出来的线程,还没有执行start方法

2)可执行状态(Runnable),这个时候已经启动了start方法,但是线程正在等待CPU轮转分配资源,从sleep,wait,这些方法里面回来的时候线程都是这个状态

3)执行状态(Running),线程已经得到了资源,开始正式运行了,有很多方法可以进入Runnable状态,但是只有一种方法能进入running状态,就是调度程序从runnable线程池里面选出一个线程运行

4)死亡(Dead),线程已经执行完run方法

5)阻塞(Blocked),资源被其他线程占据了



多线程的时候:


200326131.gif


多线程比单线程多了几种状态,一个正在running的线程可以进入任何一种non-runnable的状态,但是non-runnable不能马上进入run,需要先到runnable状态,看看几种non-runnable状态:

1)睡眠(sleeping) :在这个状态,线程还是处于alive状态,只是不可执行而已(non-runnable)

2)等待被唤醒(waiting for notification):这个线程调用了wait方法,释放了自己的资源,等待别的线程用完资源然后唤醒自己(notify)

3)I/O阻塞(blocked for I/O):等待I/O资源

4)等待其他线程完成(blocked for join completion):调用了其他线程的join方法,所以阻塞了

5)死锁(blocked for lock acquisition):两个线程都在等同一个资源,而且都不肯放手,当然阻塞




2.4 两种方式停止线程(Two Approaches to Stopping a Thread)

先说重要的一种,使用interrupt方法终止线程,Interrupting a Thread


package com.yellow.chapteOne;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class SwingTypeTester extends JFrame {
    private JButton stopButton;//停止按钮
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
    private JButton startButton;//开始按钮
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
    private MyJLabel displayBorad;//数字显示的面板
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
    private Thread thread;
    public SwingTypeTester() {
        init();
    }
    private void init() {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
        JPanel p = new JPanel();
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
        startButton = new JButton("start");
        stopButton = new JButton("stop");
        displayBorad = new MyJLabel("0");
        p.add(startButton);
        p.add(stopButton);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
        add(p, BorderLayout.SOUTH);
        add(displayBorad,BorderLayout.NORTH);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
        startButton.addActionListener(new ActionListener() {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
            @Override
            public void actionPerformed(ActionEvent e) {//点击开始按钮后启动另一个线程
                thread = new Thread(displayBorad);
                thread.start();
            }
        });
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
        stopButton.addActionListener(new ActionListener() {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
            @Override
            public void actionPerformed(ActionEvent e) {
                thread.interrupt();
            }
        });
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
        pack();
    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
    public static void main(String[] args) {
        new SwingTypeTester().show();
    }
}



package com.yellow.chapteOne;
import java.util.Random;
import javax.swing.JLabel;
/**
 * 创建线程的第二种方式,实现Runnable接口,然后传入Thread类里面执行
 * @author yellowbaby
 *
 */
public class MyJLabel extends JLabel implements Runnable{
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
    private static Random random = new Random();
    public MyJLabel(String string) {
        super(string);
    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            setText(String.valueOf(random.nextInt()));
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                return;
            }
        }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
    }
}


interrupt方法有两个作用


1)能让所有的阻塞方法(blocked method)抛出InterruptedException异常,阻塞方法也就是 sleep,wait,join这些方法,比如你sleep(一年),然后后悔了怎么办,就可以用interrupt方法

2)改变了线程的中断状态,仅仅是改变了中断状态而已,对非阻塞方法没有任何影响,也就是isInterrupted()方法的返回值


现在再来看我们的程序,我们点击stop后,调用了线程的interrupt方法,然后妥妥的isInterrupted()的值改变了,我们的程序停下来了,而且一旦执行sleep方法,我们就会抛出异常,然后return,线程马上停止


第二种终止线程的方法,使用标志变量 Setting a Flag


package com.yellow.chapteOne;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class SwingTypeTester extends JFrame {
    private JButton stopButton;//停止按钮
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
    private JButton startButton;//开始按钮
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
    private MyJLabel displayBorad;//数字显示的面板
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
    private Thread thread;
    public SwingTypeTester() {
        init();
    }
    private void init() {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
        JPanel p = new JPanel();
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
        startButton = new JButton("start");
        stopButton = new JButton("stop");
        displayBorad = new MyJLabel("0");
        p.add(startButton);
        p.add(stopButton);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
        add(p, BorderLayout.SOUTH);
        add(displayBorad,BorderLayout.NORTH);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
        startButton.addActionListener(new ActionListener() {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
            @Override
            public void actionPerformed(ActionEvent e) {//点击开始按钮后启动另一个线程
                thread = new Thread(displayBorad);
                displayBorad.setFlag(true);
                thread.start();
            }
        });
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
        stopButton.addActionListener(new ActionListener() {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
            @Override
            public void actionPerformed(ActionEvent e) {
                displayBorad.setFlag(false);
            }
        });
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
        pack();
    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
    public static void main(String[] args) {
        new SwingTypeTester().show();
    }
}



package com.yellow.chapteOne;
import java.util.Random;
import javax.swing.JLabel;
/**
 * 创建线程的第二种方式,实现Runnable接口,然后传入Thread类里面执行
 * @author yellowbaby
 *
 */
public class MyJLabel extends JLabel implements Runnable{
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
    private boolean flag = true;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
    private static Random random = new Random();
    public MyJLabel(String string) {
        super(string);
    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
    public void setFlag(boolean flag) {
        this.flag = flag;
    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
    @Override
    public void run() {
        while (flag) {
            setText(String.valueOf(random.nextInt()));
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                return;
            }
        }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
    }
}



这种方式比较简单了,设置一个flag,点击stop后直接设为false,但是这种方法有延时,因为,如果正在执行sleep的时候,会一直执行完再推出,没有interrupt那么暴力,直接抛出异常然后返回


2.5 Runnable接口(The Runnable Interface)

前面我们提到了Rrunnable接口,和继承Thread类比,用Runnable能够让我们把task和执行task的Thread分开,避免多继承的局限,一个类可以继承多个接口而且还可以方便数据共享


2.6 线程和对象(Threads and Objects)


每个线程都是一个对象,可以被传递给其他任何对象执行,有时候你如果想知道执行当前代码的到底是个线程,使用Thread.currentThread()方法