
进程
线程
同步:排队执行,效率低但是安全。
异步:同时执行,效率高但是数据不安全。
并发:两个或多个事件同时在同一个时间段内发生
并行:两个或多个事件在同一时刻发生
继承了Thread的子类为线程类
run()线程要执行的任务方法,在继承时被重写
run方法的方法体就是一条新的执行路径,其触发方式不是调用run(),而是调用Tread类的方法start()来启动任务
public static void main(String[] args) throws IOException {
MyThread mt = new MyThread();
mt.**start()**;
for (int i = 0; i < 5; i++) {
System.out.println("main"+i);
}
}
public class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("run"+i);
}
}
}
>>> main0 main1 main2 main3 run0 main4 run1 run2 run3 run4通过匿名内部类实现线程
public static void main(String[] args) throws IOException {
new Thread(){
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("thread"+i);
}
}
}.start();
for (int i = 0; i < 5; i++) {
System.out.println("main"+i);
}
}
>>> thread0 main2 thread1 main3 thread2 main4 thread3 thread4构造方法
Thread()
Thread(Runnable target)
Thread(Runnable target, String name)
Thread(String name)成员方法
public final String getName() 返回此线程的名称。
public void run() 如果此线程是使用单独的Runnable运行对象构造的,则调用该Runnable对象的run方法; 否则,此方法不执行任何操作并返回。
public final void setPriority(int newPriority) 更改此线程的优先级。
public void start() 导致此线程开始执行; Java虚拟机调用此线程的run方法。
public void stop() **已经过时的方法,**本质是不安全的。
public static void sleep(long millis) throws InterruptedException 导致当前正在执行的线程休眠(暂时停止执行)指定的毫秒数,具体取决于系统计时器和调度程序 的精度和准确性。 该线程不会失去任何监视器的所有权。
public static Thread currentThread() 返回对当前正在执行的线程对象的引用sleep()
public static void sleep(long millis) throws InterruptedException 导致当前正在执行的线程休眠(暂时停止执行)指定的毫秒数, 具体取决于系统计时器和调度程序的精度和准确性。 该线程不会失去任何监视器的所有权。
public static void sleep(long millis, int nanos) throws InterruptedException 导致当前正在执行的线程休眠(暂时停止执行)指定的毫秒数加上指定的纳秒数, 具体取决于系统定时器和调度程序的精度和准确性。 该线程不会失去任何监视器的所有权。 参数 millis - 以毫秒为单位的睡眠时间长度 nanos - 0-999999睡觉的额外纳秒 异常 IllegalArgumentException - 如果 millis值为负数,或者值 nanos不在 0-999999范围内 InterruptedException - 如果有任何线程中断了当前线程。 抛出此异常时,将清除当前线程的中断状态
for (int i = 0; i < 10; i++) {
System.out.println(i);
Thread.sleep(1000);
}
字段
| 变量和类型 | 字段 | 描述 |
|---|---|---|
| static int | MAX_PRIORITY | 线程可以拥有的最大优先级 |
| static int | MIN_PRIORITY | 线程可以拥有的最小优先级 |
| static int | NORM_PRIORITY | 分配给线程的默认优先级 |
实现Runnable接口的子类为线程类,其实例为一个任务对象
run()线程要执行的任务方法,在继承时被重写,其触发方式不是调用run(),而是调用Tread类的方法start()来启动任务
实现Runnable类对象,需要:
创建一个任务对象(Runnable 类)
创建一个线程,并为其分配一个任务
执行该线程
public static void main(String[] args) throws IOException {
MyRunnable mr = new MyRunnable();
Thread t = new Thread(mr);
t.start();
for (int i = 0; i < 5; i++) {
System.out.println("main"+i);
}
}
public class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("Runnable run"+i);
}
}
}
>>> main0 main1 Runnable run0 main2 Runnable run1 main3 main4 Runnable run2 Runnable run3 Runnable run4实现Runnable与继承Thread相比的好处:
通过创建任务然后分配给线程的方式来实现的多线程,更适合多个线程同时执行相同任务的情况
可以避免单继承带来的局限性
任务与线程本身是分离的,提高了程序的健壮性
后续学习的线程池技术能接受Runnable类型的任务而不接受Thread类型的线程
public static Thread currentThread() 返回对当前正在执行的线程对象的引用
public final String getName() 返回此线程的名称
public final void setName(String name) 将此线程的名称更改为等于参数name设置/获取线程名称
public class Test {
public static void main(String[] args) throws IOException {
System.out.println(Thread.currentThread().getName()); //主线程
new Thread(new MyRunnable(),"他日我若为青帝").start(); //子线程
}
static class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
}
>>> main 他日我若为青帝
public class Test {
public static void main(String[] args) throws IOException {
System.out.println(Thread.currentThread().getName());
new Thread(new MyRunnable()).start(); //不设置线程名称其也会有默认的名称
new Thread(new MyRunnable()).start();
new Thread(new MyRunnable()).start();
}
static class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
}
>>> main Thread-0 Thread-2 Thread-1线程阻塞
不仅指线程休眠,还指所有需要消耗较长时间的操作。
线程中断一个线程的中断是一个独立的执行路径,它是否应该结束,应该由其自身决定
调用stop()可能导致强制线程停止执行,造成异常,本质上是不安全的,因此这个方法已经过时
中断标记public void interrupt() 中断此线程中断异常
public class InterruptedException extends Exception
设置try-catch捕获线程的中断异常
public class Test {
public static void main(String[] args) throws IOException, InterruptedException {
Thread t1 = new Thread(new MyRunnable());
t1.start();
for (int i = 1; i <= 5; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
t1.interrupt(); //给t1线程添加中断标记
}
static class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) { //如果发现中断标记
//e.printStackTrace();
System.out.println("发现中断异常,线程自杀");
return; //结束任务
}
}
}
}
}
>>> main:1 Thread-0:1 main:2 Thread-0:2 main:3 Thread-0:3 main:4 Thread-0:4 main:5 Thread-0:5 发现中断异常,线程自杀守护线程
当最后一个用户进程结束时,所有守护线程自动死亡
public final void setDaemon(boolean on) 将此主题标记为daemon线程或用户线程。 当运行的唯一线程都是守护程序线程时,JVM将退出。 **必须在启动线程之前调用此方法。 ** 参数 on - 如果为 true ,则将此线程标记为守护程序线程
public class Test {
public static void main(String[] args) throws IOException, InterruptedException {
Thread t1 = new Thread(new MyRunnable());
/
service.schedule(new Runnable() {
@Override
public void run() {
System.out.println("执行任务");
}
},5,TimeUnit.SECONDS);
周期执行
ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
service.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("执行任务");
}
},5,3,TimeUnit.SECONDS);
>>> 执行任务 执行任务 执行任务 … 执行任务lambda表达式
Lambda 表达式,也可称为闭包,允许把函数作为一个方法的参数(函数作为参数传递进方法中),是推动 Java 8 发布的最重要新特性。
体现了函数式编程思想,使用 Lambda 表达式可以使代码变的更加简洁紧凑。
语法(parameters) -> expression
//或
(parameters) ->{ statements; }
特征
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值。
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("不使用lambda表达式");
}
});
t.start();
Thread t = new Thread(()-> System.out.println("使用lambda表达式"));
t.start();
public static void main(String[] args) {
print(new Mymath() {
@Override
public int sum(int x, int y) {
return x+y;
}
},100,200);
}
public static void print(Mymath m, int x, int y) {
int num = x + y;
System.out.println(num);
}
static interface Mymath {
int sum(int x, int y);
}
public static void main(String[] args) {
print((int x, int y)->{
return x+y;
},100,200);
}
public static void print(Mymath m, int x, int y) {
int num = x + y;
System.out.println(num);
}
static interface Mymath {
int sum(int x, int y);
}
保留参数部分,保留方法体