线程的概念
线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。
每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程。每个线程都可以或不可以标记为一个守护程序。当某个线程中运行的代码创建一个新 Thread 对象时,该新线程的初始优先级被设定为创建线程的优先级,并且当且仅当创建线程是守护线程时,新线程才是守护程序。 当 Java 虚拟机启动时,通常都会有单个非守护线程(它通常会调用某个指定类的 main 方法)。Java 虚拟机会继续执行线程,直到下列任一情况出现时为止:
调用了 Runtime 类的 exit 方法,并且安全管理器允许退出操作发生。 非守护线程的所有线程都已停止运行,无论是通过从对 run 方法的调用中返回,还是通过抛出一个传播到 run 方法之外的异常。【1】
线程的创建
创建新执行线程有两种方法。
一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的run 方法。
1.将类声明为 Thread 的子类
public class MyThread extends Thread {
private String info;
public MyThread(String info) {
this.info = info;
}
@Override
public void run() {
for(int i = 0; i < 5; i++) {
System.out.println(info+" == "+i);
}
}
}
测试类
public class Main {
public static void main(String[] args) {
MyThread myThread = new MyThread("线程1");
MyThread myThread2 = new MyThread("线程2");
myThread.start();
myThread2.start();
}
}
结果
线程1 == 0
线程2 == 0
线程1 == 1
线程2 == 1
线程1 == 2
线程2 == 2
线程1 == 3
线程2 == 3
线程1 == 4
线程2 == 4
2.创建线程的另一种方法是声明实现 Runnable 接口的类。
- 该类然后实现 run 方法。然后可以分配该类的实例,在创建Thread 时作为一个参数来传递并启动。
public class RunnableDemo implements Runnable{
private String name;
public RunnableDemo(String name) {
this.name = name;
}
@Override
public void run() {
for(int i = 0; i < 5; i++) {
System.out.println(this.name + " " + i);
}
}
}
测试-01
public class RunnableTest {
public static void main(String[] args) {
Runnable runnable = new RunnableDemo("张一");
Runnable runnable2 = new RunnableDemo("张二");
// runnable.run();
// runnable2.run();
Thread thread = new Thread(runnable);
Thread thread1 = new Thread(runnable2);
thread.start();
thread1.start();
}
}
结果-01
张二 0
张二 1
张一 0
张一 1
张一 2
张一 3
张一 4
张二 2
张二 3
张二 4
测试-02
public class RunnableTest {
public static void main(String[] args) {
Runnable runnable = new RunnableDemo("张一");
Runnable runnable2 = new RunnableDemo("张二");
runnable.run();
runnable2.run();
// Thread thread = new Thread(runnable);
// Thread thread1 = new Thread(runnable2);
// thread.start();
// thread1.start();
}
}
结果-02
张一 0
张一 1
张一 2
张一 3
张一 4
张二 0
张二 1
张二 2
张二 3
张二 4
线程小结
1.RunnableDemo中写了2个测试,是为了说明一个问题:
启动线程的方式——Thread对象上调用start()方法,而非run()或者别的方法。run()方法并不启动新的线程。
2.拓展(以下内容可跳过)
public class Thread
extends Object
implements Runnable
Thread是Runnable接口的实现类。查看Thread源码,实现run()方法如下:
/**
* If this thread was constructed using a separate
* <code>Runnable</code> run object, then that
* <code>Runnable</code> object's <code>run</code> method is called;
* otherwise, this method does nothing and returns.
* <p>
* Subclasses of <code>Thread</code> should override this method.
*
* @see #start()
* @see #stop()
* @see #Thread(ThreadGroup, Runnable, String)
*/
@Override
public void run() {
if (target != null) {
target.run();
}
}
1.target是什么?
/* What will be run. */
private Runnable target;
2.target的初始化?
/**
* Allocates a new {@code Thread} object. This constructor has the same
* effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
* {@code (null, null, gname)}, where {@code gname} is a newly generated
* name. Automatically generated names are of the form
* {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
*/
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
/**
* Allocates a new {@code Thread} object. This constructor has the same
* effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
* {@code (null, target, gname)}, where {@code gname} is a newly generated
* name. Automatically generated names are of the form
* {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
*
* @param target
* the object whose {@code run} method is invoked when this thread
* is started. If {@code null}, this classes {@code run} method does
* nothing.
*/
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
3.init是什么?
/**
* Initializes a Thread.
*
* @param g the Thread group
* @param target the object whose run() method gets called
* @param name the name of the new Thread
* @param stackSize the desired stack size for the new thread, or
* zero to indicate that this parameter is to be ignored.
* @param acc the AccessControlContext to inherit, or
* AccessController.getContext() if null
*/
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc) {
//...
}
4.Thread的start()方法
/**
* Causes this thread to begin execution; the Java Virtual Machine
* calls the <code>run</code> method of this thread.
* <p>
* The result is that two threads are running concurrently: the
* current thread (which returns from the call to the
* <code>start</code> method) and the other thread (which executes its
* <code>run</code> method).
* <p>
* It is never legal to start a thread more than once.
* In particular, a thread may not be restarted once it has completed
* execution.
*
* @exception IllegalThreadStateException if the thread was already
* started.
* @see #run()
* @see #stop()
*/
public synchronized void start() {
//...
}