版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
在 Java 中实现多线程有两种手段,一种是继承 Thread 类,另一种就是实现 Runnable 接口。
Java 提供了三种创建线程的方法:
- 通过实现 Runnable 接口;
- 通过继承 Thread 类本身;
- 通过 Callable 和 Future 创建线程。
RunnableDemo.java
/**
* @author: 毛利
*/
class RunnableDemo implements Runnable {
private Thread t;
private String threadName;
RunnableDemo( String name) {
//
threadName = name;
System.out.println("Creating " + threadName );
}
public void run() {
System.out.println("Running " + threadName );
try {
for(int i = 4; i > 0; i--) {
System.out.println("Thread: " + threadName + ", " + i);
// 让线程睡眠一会0.05
Thread.sleep(50);
}
}catch (InterruptedException e) {
System.out.println("Thread " + threadName + " interrupted.");
}
System.out.println("Thread " + threadName + " exiting.");
}
public void start () {
System.out.println("Starting " + threadName );
if (t == null) {
t = new Thread (this, threadName);
t.start ();
}
}
}
TestThread.java
/**
* @author: 毛利
*/
public class TestThread {
public static void main(String args[]) {
RunnableDemo R1 = new RunnableDemo( "Thread-1");
R1.start();
RunnableDemo R2 = new RunnableDemo( "Thread-2");
R2.start();
}
}
实现 Runnable 接口
- main入口函数创建线程
- 线程执行的run方法,所以继承Runnable接口,改写run方法
public class CreateThreadAppMain {
/*
创建线程打印TEXT
*/
// 定义变量TEXT不可变
private static final String TEXT = "私の名前はもうり、今日はJavaを勉強する\n" +
"......";
public static void main(String[] args) {
// TODO 代码是被线程执行的,任何代码都可以通过Thread.currentThread()获取执行当前代码的线程
// TODO 通过getName方法来获取线程的名字main
System.out.println("程序开始,执行的线程名字叫做" + Thread.currentThread().getName());
// TODO 如果改成2 线程-1先执行 线程-2慢执行 因为遍历需要时间
for (int i = 1; i <= 1; i++) {
// 学习创建线程的方法
// TODO Runnable接口里的run是线程执行的方法,执行完毕,线程就结束了
// TODO PrintStoryRunnable 需要改写run方法
Thread thread = new Thread(new PrintStoryRunnable(TEXT, 200 * i), "我的线程-" + i);
// TODO 创建好线程之后,如果要启动线程,必须调用start方法,注意不是run方法 但是执行的是run方法
thread.start();
}
System.out.println("启动线程结束,名字叫做" + Thread.currentThread().getName());
}
// TODO 实现 Runnable 接口
static class PrintStoryRunnable implements Runnable {
private String text;
private long interval;
public PrintStoryRunnable(String text, long interval) {
this.text = text;
this.interval = interval;
}
// 改为run方法
@Override
public void run() {
try {
System.out.println("执行这段代码的线程名字叫做" + Thread.currentThread().getName());
printSlowly(text, interval);
System.out.println(Thread.currentThread().getName() + "执行结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void printSlowly(String text, long interval) throws InterruptedException {
for (char ch : text.toCharArray()) {
Thread.sleep(interval);
System.out.print(ch);
}
System.out.println();
}
}
守护线程
Java分为两种线程:用户线程和守护线程
如果我们不将一个线程以守护线程方式来运行,即使主线程已经执行完毕,程序也永远不会结束,可以尝试把上述将线程设为守护线程的那句注释掉,重新运行看看结果:
- 就是main函数结束了,你这个线程就不要跑了,来保护你
只要添加thread.setDaemon(true);
在补充优先级就ok了 thread.setPriority(Thread.MAX_PRIORITY);
public class DaemonThreadAppMain {
private static final String TEXT = "私の名前はもうり、今日はJavaを勉強する\n" +
"......";
public static void main(String[] args) throws InterruptedException {
System.out.println("程序开始,执行的线程名字叫做" + Thread.currentThread().getName());
for (int i = 1; i <= 1; i++) {
Thread thread = new Thread(new PrintStoryRunnable(TEXT, 200 * i), "我的线程-" + i);
// TODO 可以在start之前设置线程为守护线程
thread.setDaemon(true);
// TODO 可以随时改变线程(和是不是守护线程没有关系)的优先级,但是作用不能保证
thread.setPriority(Thread.MAX_PRIORITY);
thread.start();
}
System.out.println("启动线程结束,名字叫做" + Thread.currentThread().getName());
}
static class PrintStoryRunnable implements Runnable {
private String text;
private long interval;
public PrintStoryRunnable(String text, long interval) {
this.text = text;
this.interval = interval;
}
@Override
public void run() {
try {
System.out.println("执行这段代码的线程名字叫做" + Thread.currentThread().getName());
printSlowly(text, interval);
System.out.println(Thread.currentThread().getName() + "执行结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void printSlowly(String text, long interval) throws InterruptedException {
for (char ch : text.toCharArray()) {
Thread.sleep(interval);
System.out.print(ch);
}
System.out.println();
}
}
执行就不会打印TEXT