进程与线程
*程序:无任何运行含义,是一个静态的概念
*进程:执行程序的一次执行过程
*线程:CPU调度和执行的单位,一个进程中可以包含若干个线程
进程中有main(主方法)线程、gc线程(垃圾回收),main()为主线程,程序入口
一个CPU一次只能执行单个线程,多线程=多CPU(多核)
线程状态
1.创建状态:Tread t = new Thread()创建线程
2.就绪状态:调用t.start()方法,进入就绪状态,但是并没有被CPU调度执行
3.运行状态:被CPU调度执行线程体的代码块
4.阻塞状态:调用t.sleep(),t.wait()或同步锁定时,代码不继续往下执行,阻塞时间结束后,重新进入就绪状态等待CPU调度执行
5.死亡状态:线程中断或结束。一旦死亡就不能再次启动。
线程创建
创建方式:继承Thread类、实现Runanable接口、实现Callable接口
Thread类创建进程
重写run方法,通过start异步调用run方法启动线程
class test extends Thread{
public void run(){
for(int i=0 ; i<100 ; i++){
System.out.println("BBBBBBBBBBBBBB");
}
}
}
public class Threads{
public static void main(String args[]){
new test().start();
for(int i=0 ; i<100 ; i++){
System.out.println("AAAAAAAAAAAAAA");
}
}}
结果中AAAAAAAA与BBBBBBBBBB随机排布,说明test类中创建的线程是和main中的线程是交替执行的,具体执行逻辑由CPU分配。
利用多线程同时下载多个文件
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
class download extends Thread{
String url;
String name;
public download(String url,String name){
this.url = url;
this.name = name;
}
public void run(){
try {
FileUtils.copyURLToFile(new URL(url), new File(name));
} catch (IOException e) {
throw new RuntimeException(e);
}
System.out.printf("下载了文件%s\n",name);
}
public static void main(String a[]){
new download("https://mak4r1.com/wp-content/uploads/2024/07/1722136018-204a4d6d5d6dd8064ebd140cfb9c5dfc-1536x1536.jpg","图片1.jpg").start();
new download("https://mak4r1.com/wp-content/uploads/2024/07/1722136022-a07ce38bd1f99922e5d61d4ad641f159-1536x1536.jpg","图片2.jpg").start();
new download("https://mak4r1.com/wp-content/uploads/2024/07/1722136022-61df6e36021b106e697cf59365d1c5ed-1536x1536.jpg","图片3.jpg").start();
new download("https://mak4r1.com/wp-content/uploads/2024/07/1722136024-23f63fb11203d159c8e2ed725b2efc8e-1536x1536.jpg","图片4.jpg").start();
}
}
实现Runnable接口
实现Runnable接口的类重写run方法,实例作为参数传给new Thread并执行start()
public class testRunnable implements Runnable{
public void run(){
System.out.println("Test Runnable");
}
public static void main(String a[]){
new Thread(new testRunnable()).start();
}
}
可以利用lambda表达式,表达的是run方法
public class testRunnable{
public static void main(String a[]){
new Thread(()-> {System.out.println("Test Runnable");}).start();
}
}
实现Callable接口
执行run方法返回Boolean类型,使用线程时创建线程池服务并提交线程对象,开启线程,停止服务。
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;
class download implements Callable<Boolean> {
String url;
String name;
public download(String url,String name){
this.url = url;
this.name = name;
}
public Boolean call(){
try {
FileUtils.copyURLToFile(new URL(url), new File(name));
} catch (IOException e) {
throw new RuntimeException(e);
}
System.out.printf("下载了文件%s\n",name);
return true;
}
public static void main(String a[]) throws ExecutionException, InterruptedException {
download d1 = new download("https://mak4r1.com/wp-content/uploads/2024/07/1722136018-204a4d6d5d6dd8064ebd140cfb9c5dfc-1536x1536.jpg","图片1.jpg");
download d2 = new download("https://mak4r1.com/wp-content/uploads/2024/07/1722136022-a07ce38bd1f99922e5d61d4ad641f159-1536x1536.jpg","图片2.jpg");
download d3 = new download("https://mak4r1.com/wp-content/uploads/2024/07/1722136022-61df6e36021b106e697cf59365d1c5ed-1536x1536.jpg","图片3.jpg");
download d4 = new download("https://mak4r1.com/wp-content/uploads/2024/07/1722136024-23f63fb11203d159c8e2ed725b2efc8e-1536x1536.jpg","图片4.jpg");
ExecutorService ser = Executors.newFixedThreadPool(4);
Future<Boolean> s1 = ser.submit(d1);
Future<Boolean> s2 = ser.submit(d2);
Future<Boolean> s3 = ser.submit(d3);
Future<Boolean> s4 = ser.submit(d4);
boolean rs1 = s1.get();
boolean rs2 = s2.get();
boolean rs3 = s3.get();
boolean rs4 = s4.get();
ser.shutdown();
}
}
Runnable接口和Callable接口的实现,相当于对对象进行了一次静态代理(在其他类的方法中帮忙执行本类的方法)
并发问题
多个线程操作统一资源时产生的资源紊乱,导致进程不安全,例子:
public class testRunnable implements Runnable{
static int apples = 10;
public void run(){
while (apples > 0){
try {
Thread.sleep(200);// 线程的模拟延时
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.printf("%s吃掉了第%d个苹果。\n",Thread.currentThread().getName(),11-(apples--));
}
}
public static void main(String a[]){
new Thread(new testRunnable(),"小明").start();
new Thread(new testRunnable(),"小红").start();
new Thread(new testRunnable(),"小兰").start();
}}
Comments NOTHING