进程和线程
线程的创建
java中创建线程的方式有5种
- 继承Thread类,重写run方法
- 实现Runnable,重写run方法
- 使用匿名内部类继承Thread类,重写run方法
- 使用匿名内部类实现Runnable,重写run方法
- lambda表达式
推荐lambda表达式,最方便
//lambda表达式实现
public class Demo5 {
public static void main(String[] args) {
Thread t = new Thread(() -> {
while(true){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
}
}
run描述了线程要做的工作,真正线程开始运行,则是靠start方法
多线程
虽然多进程也能完成并发编程但是线程比进程更轻量
- 线程的创建和销毁比进程开销小
- 线程的调度比进程的开销小
利用多线程编程提高效率
public class Demo6 {
//100亿 - 数据量越大多线程的优势才会展现,因为线程的创建和销毁也是有开销的
private static final long COUNT = 100_0000_0000L;
//利用多线程提高效率
public static void main(String[] args) throws InterruptedException {
// serial();
concurrency();
}
//串行执行任务
public static void serial() throws InterruptedException {
long startTime = System.currentTimeMillis();
long a = 0;
for(long i = 0; i < COUNT; i++){
a++;
}
a = 0;
for(long i = 0; i < COUNT; i++){
a++;
}
long endTime = System.currentTimeMillis();
System.out.println("执行的时间间隔:" + (endTime - startTime) + "ms");
}
//并发执行任务
public static void concurrency(){
long startTime = System.currentTimeMillis();
Thread t1 = new Thread(() -> {
long i = 0;
for (long j = 0; j < COUNT; j++) {
i++;
}
});
Thread t2 = new Thread(() -> {
long i = 0;
for (long j = 0; j < COUNT; j++) {
i++;
}
});
t1.start();
t2.start();
//t1,t2,main都是并发执行,而我们要计算的时间是t1,t2执行完后的时间,所以要让main线程进行阻塞等待
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println("执行的时间间隔:" + (endTime - startTime) + "ms");
}
}
线程中断和线程等待
线程中断的实质只是让run方法尽快结束并不是直接强行结束run方法。
java中有两种方法中断线程
- 自己设置标志位来控制线程中断
- 通过线程的isInterrupt方法来判定,用interrup方法来中断
线程等待 - join()方法
在main线程上调用t.join()意思是让main线程等待t线程执行结束。
join(可以加上等待时间)加上时间就是过时不候,不加时间就是不见不散。
public class Demo10 {
//线程中断
//线程中断是让run方法尽快结束,而不是强行结束
//1.自己设置标志位来控制线程中断
//2.通过线程的isInterrupt方法来中断
private static boolean isQuit = false;
public static void main(String[] args) {
Thread t = new Thread(() -> {
// while(!isQuit){
while(!Thread.currentThread().isInterrupted()){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
//1.立即结束进程
// break;
//2.不予理会
// e.printStackTrace();
//3.稍后处理
// Thread.sleep(1000);
// break;
}
}
});
t.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//要不要中断线程取决于你代码的写法
t.interrupt();
// isQuit = true;
}
}
public class Demo11 {
//线程阻塞等待 join()
public static void main(String[] args) {
Thread t = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
System.out.println("线程join之前");
try {
// t.join();//无限等待
t.join(3000);//过时不候
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程join之后");
}
}
线程休眠
Thread.sleep(millis);让当前线程休眠一段时间
获取线程实例
Thread.currentThread();通过这个方法就获得了线程实例,就像this一样代表当前线程引用。
谈谈线程和进程之间的区别【高频】
- 进程包含线程(一个进程有有一个或多个线程)
- 线程比进程更轻量,创建更快,销毁更快
- 同一个进程中的不同线程共用同一份内存文件/资源,进程和进程之间,则是独立的内存资源
- 进程是资源分配的基本单位,线程是调度分析的基本单位