首页 > 编程语言 > 详细

Java多线程详解(1)

时间:2021-02-13 09:01:28      阅读:50      评论:0      收藏:0      [点我收藏+]

多线程详解

1、线程简介

  ①多任务—用户可以在同一时间内运行多个应用程序,每个应用程序被称作一个任务

  ②多线程—多个线程并发执行

        技术分享图片     技术分享图片

 

  ③程序、进程、线程

      程序—指令和数据的有序集合,是静态的概念

      进程—执行程序的一次执行过程,是动态的概念,系统资源分配的单位

      线程—独立执行的路径,是CPU调度和执行的单位,一个进程至少有一个线程

 

2、线程的创建

  ①三种创建方式

      1.继承Thread类

      2.实现Runnable接口

      3.实现Callable接口

  ②通过Thread类创建

      1.自定义线程类继承Thread类

      2.重写run()方法,编写线程执行体

      3.创建线程对象,调用start()方法启动线程

 1 public class TestThread1 extends Thread{
 2     @Override
 3     public void run() {
 4         //run()方法线程体
 5         for(int i=0;i<20;i++){
 6             System.out.println("我正在编程------"+i);
 7         }
 8     }
 9 ?
10     public static void main(String[] args) {
11         //main线程,主线程
12         //线程开启不一定立即执行,由CPU调度安排
13         TestThread1 testThread1=new TestThread1();
14         //testThread1.run();//在主线程中顺序执行
15         testThread1.start();//在主线程中交替执行
16 ?
17         for(int i=0;i<2000;i++){
18             System.out.println("我正在学习多线程------"+i);
19         }
20     }
21 }

  ③通过Runnable接口创建

      1.定义一个类实现Runnable接口

      2.重写run()方法,编写线程执行体

      3.创建线程对象,调用start()方法启动线程

  好处是避免了单继承局限性,灵活方便,方便同一个对象被多个线程使用

 1 public class TestThread3 implements Runnable{
 2     @Override
 3     public void run() {
 4         //run()方法线程体
 5         for(int i=0;i<20;i++){
 6             System.out.println("我正在编程------"+i);
 7         }
 8     }
 9 ?
10     public static void main(String[] args) {
11         //创建Runnable接口的实现类对象
12         TestThread3 testThread3=new TestThread3();
13 ?
14         //创建线程对象,通过线程对象来开启线程
15         new Thread(testThread3).start();
16 ?
17         for(int i=0;i<2000;i++){
18             System.out.println("我正在学习多线程------"+i);
19         }
20     }
21 }

  ④实现Callable接口

      1.实现Callable接口,需要返回值类型

      2.重写call方法,需要抛出异常

      3.创建目标对象

      4.创建执行服务器:ExecutorService ser=Executors.newFixedThreadPool(1);

      5.提交执行:Future<Boolean> result1=ser.submit(t1);

      6.获取结果:boolean r1=result1.get();

      7.关闭服务:ser.shutdownNow();

 1 public class TestCallable implements Callable<Boolean> {
 2     private String url;
 3     private String name;
 4 ?
 5     public TestCallable(String url,String name){
 6         this.url=url;
 7         this.name=name;
 8     }
 9 ?
10     @Override
11     public Boolean call() throws Exception {
12         WebDownloader1 webDownloader=new WebDownloader1();
13         webDownloader.downloader(url,name);
14         System.out.println("下载文件名为"+name);
15         return true;
16     }
17 ?
18     public static void main(String[] args) throws ExecutionException, InterruptedException {
19         TestCallable t1=new TestCallable("http://commons.apache.org/proper/commons-io/images/commons-logo.png","6.jpg");
20 ?
21         //创建执行服务
22         ExecutorService ser= Executors.newFixedThreadPool(1);//创建线程池,需要1个线程
23 ?
24         //提交执行
25         Future<Boolean> r1=ser.submit(t1);
26 ?
27         //获取结果
28         boolean rs1=r1.get();
29 ?
30         //关闭服务
31         ser.shutdownNow();
32     }
33 }
34 ?
35 //下载器
36 class WebDownloader1{
37     //下载方法
38     public void downloader(String url,String name){
39         try {
40             FileUtils.copyURLToFile(new URL(url),new File(name));
41         } catch (IOException e) {
42             System.out.println("IO异常,downloader出现了问题");
43         }
44     }
45 }

 

3、静态代理模式

  ①真实对象和代理对象都要实现同一个接口

  ②代理对象要代理真实角色

  ③好处

      1.代理对象可以做很多真实对象做不了的事情

      2.真实对象专注做自己的事情

 1 public class StaticProxy {
 2     public static void main(String[] args) {
 3         You you=new You();
 4         marryCompany marry=new marryCompany(you);
 5         marry.getMarry();
 6     }
 7 }
 8 ?
 9 interface Marry{
10     void getMarry();
11 }
12 ?
13 ?
14 class You implements Marry{
15     @Override
16     public void getMarry() {
17         System.out.println("You------>Marry");
18     }
19 }
20 ?
21 class marryCompany implements Marry{
22     private You you;
23     public marryCompany(You you){
24         this.you=you;
25     }
26     @Override
27     public void getMarry() {
28         befor();
29         you.getMarry();
30         after();
31     }
32     public void befor(){
33         System.out.println("结婚前,要布置现场");
34     }
35     public void after(){
36         System.out.println("结婚后,收尾款");
37     }
38 }

 

4、Lamda表达式

  ①避免了匿名内部类定义过多;让代码看起来更简洁;去掉了一堆没有意义的代码,只留下核心逻辑

  ②函数式接口(Functional Interface)—只包含唯一一个抽象方法

  对于函数式接口可以通过Lamda表达式来创建该接口的对象

 1 public class TestLamda {
 2     public static void main(String[] args) {
 3         //Lamda简化
 4         ILove love=(int a)->{
 5             System.out.println("I Love------>"+a);
 6         };
 7         love.lamda(3);
 8 ?
 9         //1.简化参数    多个参数也可以去掉参数,但要都去掉
10         ILove love1=(a)->{
11             System.out.println("I Love------>"+a);
12         };
13         love1.lamda(6);
14 ?
15         //2.简化括号    多个参数时括号不可以去掉
16         ILove love3=a->{
17             System.out.println("I Love------>"+a);
18         };
19         love3.lamda(9);
20 ?
21         //3.简化花括号   只有在方法中只有一行语句时可以去掉花括号
22         ILove love4=a->System.out.println("I Love------>"+a);
23         love4.lamda(12);
24     }
25 }
26 ?
27 interface ILove{
28     void lamda(int a);
29 }

 

5、线程状态

  ①线程状态间转换

      技术分享图片

  ②线程停止

      1.建议线程正常停止—利用次数,不建议死循环

      2.建议使用标志位—设置一个标志位

      3.不要使用stop或者destroy等过时或者JDK不建议使用的方法

 1 public class ThreadStop extends Thread{
 2 ?
 3     private boolean flag=true;
 4 ?
 5     @Override
 6     public void run() {
 7         int i=0;
 8         while(flag){
 9             System.out.println("run Thread------"+i++);
10         }
11     }
12 ?
13     public void Stop(){
14         this.flag=false;
15     }
16 ?
17     public static void main(String[] args) {
18         ThreadStop t=new ThreadStop();
19         new Thread(t).start();
20         for(int i=0;i<1000;i++){
21             if(i==900){
22                 t.Stop();
23                 System.out.println("线程该停止了");
24             }
25             System.out.println("main"+i);
26         }
27     }
28 }

  ②线程休眠

      1.sleep(时间)指定当前线程阻塞的毫秒数

      2.sleep存在异常InterruptedException

      3.sleep时间到达后线程进入就绪状态

      4.sleep可以模拟网络延迟,倒计时等

      5.sleep每一个对象都有一个锁,sleep不会释放锁

  ③线程礼让

      1.让当前正在执行的线程暂停,但不阻塞;Thread.yield()

      2.将线程从运行状态转为就绪状态

      3.礼让不一定成功

  ④线程合并

      Join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞

 1 public class TestJoin implements Runnable{
 2     @Override
 3     public void run() {
 4         for(int i=0;i<1000;i++){
 5             System.out.println("线程vip来了"+i);
 6         }
 7     }
 8 ?
 9     public static void main(String[] args) throws InterruptedException {
10         TestJoin t=new TestJoin();
11         Thread thread=new Thread(t);
12         thread.start();
13 ?
14         //主线程
15         for(int i=0;i<500;i++){
16             if(i==200){
17                 thread.join();//插队
18             }
19             System.out.println("主线程"+i);
20         }
21     }
22 }

 

6、观测线程状态

  通过Thread类的对象thread调用getState()方法

 1 public class TestState {
 2     public static void main(String[] args) throws InterruptedException {
 3         Thread thread=new Thread(()->{            //重写run()方法
 4            for(int i=0;i<5;i++){
 5                try {
 6                    Thread.sleep(1000);
 7                } catch (InterruptedException e) {
 8                    e.printStackTrace();
 9                }
10            }
11             System.out.println("执行结束了!");
12         });
13 ?
14         //观察状态
15         Thread.State state=thread.getState();
16         System.out.println(state);//NEW
17 ?
18         //观察启动后
19         thread.start();
20         state=thread.getState();
21         System.out.println(state);//RUN
22 ?
23         while(state!=Thread.State.TERMINATED){   //只要线程不终止,就一直输出状态
24             Thread.sleep(100);
25             state=thread.getState();
26             System.out.println(state);//TIMED_WAITING
27         }
28     }
29 }

 

7、线程优先级

  ①线程调度器按照优先级决定应该调度哪个线程来执行

  ②线程的优先级用数字表示,范围从1~10

      Thread.MIN_PRIORITY=1;

      Thread.MAX_PRIORITY=10;

      Thread.NORM_PRIORITY=5;

  ③通过getPriority()方法获取优先级;通过setPriority()方法改变优先级

  ④先设置优先级,再启动线程

  ⑤优先级低只意味着获得调度的概率低,并不是优先级低就不会被调用了,要看CPU的调度

 

8、守护线程

  ①线程分为用户线程和守护线程(daemon)

  ②虚拟机必须确保用户线程执行完毕,虚拟机不必等待守护线程执行完毕,如后台记录操作日志、监控内存、垃圾回收等

God god=new God();
Thread thread=new Thread(god);
thread.setDaemon(true);//默认是false,是用户线程

 

 

 

 

Java多线程详解(1)

原文:https://www.cnblogs.com/yqsumAll/p/14399270.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!