2022/10/12线程核心概念
-
线程就是独立的执行路径。
-
在程序运行时,即使自己没有创建线程,后台也会有多个线程,如主线程,gc线程。
-
main()称之为主线程,为系统的入口,用于执行整个程序。
-
在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能人为干预的
-
对同一份资源操作时,会存在资源抢夺的问题需要加入并发控制。
-
对同一份资源操作时,会存在资源抢夺问题,需要加入并发控制。
-
线程会带来额外的开销,如cpu调度时间,并发控制开销。
-
每个线程在自己的工作内存交互,内存控制不当造成数据不一致。
三种创建方式
-
Thread class:继承Thread类(重点)
-
Runnable接口:实现Runnable接口(重点)
-
Callable接口:实现Callable接口(了解)
Thread
-
-
重写run()方法,编写线程执行体
-
创建线程对象,调用start()方法启动线程
public class TestThread1 extends Thread{
public class TestThread2 extends Thread{
private String url;
private String name;
public TestThread2(String url,String name){
this.url=url;
this.name=name;
}
@Override
public void run() {
WebDownLoader webDownLoader = new WebDownLoader();
webDownLoader.downloader(url,name);
System.out.println("下载文件图片名为:"+name);
}
public static void main(String[] args) {
TestThread2 t1=new TestThread2("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Flmg.jj20.com%2Fup%2Fallimg%2F1114%2F010421143P0%2F210104143P0-4-1200.jpg&refer=http%3A%2F%2Flmg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1668094322&t=1222fed63d4d2315eb80ed377579ec90","1.jpg");
TestThread2 t2=new TestThread2("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Flmg.jj20.com%2Fup%2Fallimg%2F1114%2F010421143P0%2F210104143P0-4-1200.jpg&refer=http%3A%2F%2Flmg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1668094322&t=1222fed63d4d2315eb80ed377579ec90","2.jpg");
TestThread2 t3=new TestThread2("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Flmg.jj20.com%2Fup%2Fallimg%2F1114%2F010421143P0%2F210104143P0-4-1200.jpg&refer=http%3A%2F%2Flmg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1668094322&t=1222fed63d4d2315eb80ed377579ec90","3.jpg");
t1.start();
t2.start();
t3.start();
}
}
//下载器
class WebDownLoader{
public void downloader (String url,String name){
try {
FileUtils.copyURLToFile(new URL(url),new File(name));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Runnable
-
定义MyRunnable类实现Runnable接口
-
实现run()方法,编写线程执行体
-
创建线程对象,调用start()方法启动线程
小结
-
继承Thread类
-
子类继承Thread类具备多线程能力
-
启动线程:子类对象().start()
-
不建议使用:避免oop单继承局限性
-
-
实现Runnable接口
-
实现接口Runnable具有多线程能力
-
启动线程:传入目标对象+Thread(对象).start()
-
推荐使用:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用
-
//多个线程同时操作一个对象
//买火车票的例子
//发现问题:多个线程操作同一个资源时,线程不安全,数据紊乱。
public class TestThread4 implements Runnable{
private int ticketNums = 10;
案例
龟兔赛跑
public class Race implements Runnable{
//胜利者
public static String winner;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)