java多线程详解学习笔记

  程序:程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。 

  进程:进程则是执行程序的一次执行过程,它是一个动态的概念。是系统资源分配的单位

  通常在一个进程中可以包含若干个线程,当然一个进程中至少有一个线程,不然没有存在的意义。线程是 CPU调度和执行的单位。

  1、线程就是独立的执行路径

  2、在程序运行时,即使没有自己创建线程,后台也会有多个线程,如主线程,gc线程;

  3、main()称之为主线程,为系统的入口,用于执行整个程序;

  4、在一个进程中,如果开辟了多个线程,线程的运行由调度器(CPU)安排调度,调度器是与操作系统紧密相关的,先后顺序是不能人为的干预的。

  5、对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制;

   创建线程方式一:   1、自定义线程类继承Thread类

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

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

   总结:注意,线程开启不一定立即执行,由CPU调度执行

    创建线程方式二:   1、自定义线程类实现Runnable接口

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

                                 3、创建线程对象,调用start()方法启动线程(需要丢入runnable接口实现类,调用start方法)

   多个线程操作同一资源时会产生并发问题,引起数据紊乱。 

     创建线程方式三: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();

   静态代理模式总结:

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

   代理对象要代理真实角色,通过有参构造传入

   好处:代理对象可以做很多真实对象做不了的事情

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

   Lambda表达式:

   任何接口,如果只包含唯一一个抽象方法,那么它就是一个函数式接口。

   (方法参数)->{主体};

    简化1. 去掉参数类型

           2. 简化括号

           3. 去掉花括号

    总结:lambda表达式只能有一行代码的情况下才能简化成为一行,如果有多行,那么就用代码块包裹。

               前提是接口为函数式接口

               多个参数也可以去掉参数类型,要去掉就都去掉 ,必须加上括号。

   线程状态:

   停止线程:不推荐使用JDK提供的stop()、destroy()方法。建议使用一个标志位进行终止变量,当flag=false,则终止线程。

   线程休眠:sleep指定当前线程阻塞的毫秒数;每一个对象都有一个锁,sleep不会释放锁;

                     模拟网络延时:放大问题的发生性。

   线程礼让:让cpu重新调度,礼让不一定成功!看CPU心情(Thread.yield())

   join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞,可以想象成插队

   观测线程状态:thread(线程对象).getState();
   java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行。

   线程的优先级用数字表示,范围 从1~10   线程对象.setPriority()  设置线程优先级 不设置默认优先级为5

   优先级的设定建议在start()调度前,优先级低只是意味着获得调度的概率低,并不是优先级低就不会被调用了,这都得看cpu

   守护线程: 线程分为用户线程和守护线程  

                      虚拟机必须确保用户线程执行完毕(main())

                      虚拟机不用等待守护线程执行完毕(gc())

                      thread.setDaemon(true或false)  默认是false表示用户线程,正常的线程都是用户线程

   并发:同一个对象被多个线程同时操作

   线程同步:形成条件:队列+锁 (synchronized)       

   synchronized  默认锁的是this 同步方法和同步块

   public synchronized 返回值类型 方法名() {

   }

   synchronized(对象){  //锁的对象就是变化的量,需要增删改的对象

     可能发生线程安全问题的代码   

   }

   JUC安全类型的集合:  CopyOnWriteArrayList

   死锁:两个或多个线程各自占有一些资源,都在等待对方释放资源,都停止执行的情况,某一个同步块同时拥有"两个以上对象的锁"时,就可能发生"死锁"的问题。(简单来说就是多个线程互相抱着对方需要的资源,然后形成僵持)

   产生死锁的四个必要条件:

     1.互斥条件:一个资源每次只能被一个进程使用。

     2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

     3.不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。

     4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

     Lock锁:和synchronized差不多的东西,Lock是显式锁(手动开启和关闭锁,别忘关闭锁)  synchronized是隐式锁,出来作用域自动释放  ReentrantLock(可重入锁)

     线程通信:wait() 表示线程一直等待,直到其他线程通知,与sleep不同,会释放锁

                       notify() 唤醒一个处于等待状态的线程

     生产者消费者模型 -->  利用缓冲区解决:管程法 信号灯法

     线程池:提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中。可以避免频繁创建销毁、实现重复利用。类似生活中的公共交通工具。  

     创建服务,创建线程池,参数为线程池大小

     ExecutorService ser = Executors.newFixedThreadPool(10) ;

     执行

     ser.execute(接口的实现类对象);

     关闭连接

     ser.shutdown();

    

   

 

 

     

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值