您的位置:首页 > 其它

多线程

2020-04-24 11:03 218 查看

1、并发和并行
并发交替执行,并行同时执行

2、进程和线程
线程属于进程,是进程中的一个执行单元。通常是在一个进程中包括多个线程,每个线程都是作为利用CPU的基本单位,作为独立运行和独立调度的基本单位。
通常把进程作为分配资源的基本单位,每个进程都有一个独立的内存空间。

3、线程调度
①分时调度
所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间。
②抢占式调度:
优先级更高的线程优先使用CPU,优先级相同,随即选择,JAVA就是抢占式调度。

抢占式调度在多个线程之间进行高速切换,对于CPU的一个核而言,某时刻只能执行一个线程。多线程并不能提高程序的运行速度(对我们来说是提高的?),但能够提高程序运行效率,让CPU的使用率更高。

4、主线程:
执行main方法的线程,JVM执行main方法,方法进入栈内存,JVM找OS开辟一条main方法通向CPU的执行路径,CPU就通过这个路径执行main方法,这个路径就叫主线程。

5、多线程创建(文档有)
方法一:继承Thread类;
步骤:
①创建一个Thread类的子类;
②重写run方法,设置线程任务;
③创建Thread的子类对象;
④调用start方法,开启新线程,JVM调用该线程的 run 方法;,只能启动一次。

方法二:实现Runnable
①创建一个实现Runable接口的实现类;
②类中重写run方法,设置线程任务;
③创建实现类的对象;
④创建Thread类对象,构造方法中传递实现类对象;
⑤调用Thread中的start方法,开启线程执行 run 方法

  • 两种方法都可以用匿名内部类的方式。

用方法二创建多线程的好处:
①避免了单继承的局限性,法一要用了继承;而实现接口可以多个,也还可以继承。
②增强了程序的扩展性,降低程序耦合性;设置线程任务(重写run)和开启线程(Thread类对象的start)+进行了分离

6、多线程内存

7、Thread常用方法
①设置线程名称,获取线程的名称
②Thread.sleep()// 线程休眠,要处理异常

MyThread mt = new MyThread();
mt.setName("起名");
mt.start(); //开辟通向CPU的新路径,执行run方法,实现多线程,直接执行run方法还是单线程的
new MyThread("测试构造起名").start();
System.out.println(Thread.currentThread().getName());

8、线程安全问题:前提是多线程访问了共享数据;
可能是同时执行同一语句(下一句还没执行到),可能是完成了判断,另外的线程能超出判断范围。

解决线程安全问题:三个
9、同步代码块
synchronize(锁对象){
可能出现线程安全问题的代码
}

注意:①锁对象可以任意,但是多线程使用的是同一个;
②锁对象的作用:把同步代码锁住,只让一个线程在同步代码块中执行。

原理:使用了锁对象,这个对象叫同步锁,也叫对象锁,也叫对象监视器。
第一个先获取到锁对象,进入同步中执行,第二个线程发现没有,则进入阻塞状态,等到第一个归还锁对象后,第二个才获取到锁对象进入同步中执行。总的来说同步中的线程,没有执行完毕,不会释放锁,其他线程也就进不去。
程序频繁的判断锁,获取、释放锁,程序的效率降低

10、同步方法
①可能出现线程安全问题的代码,放到一个带 synchronize 方法中;
②同步方法的锁对象是this,就是new RunnableImpl()

还有静态同步方法:锁对象是本类的class属性(class文件对象(反射))

11、Lock锁(更好)
步骤:
①在成员位置创建一个ReentrantLock对象(Lock接口实现类)(多态)
②可能出现线程安全问题前调用Lock接口中的lock方法获取锁;
③结束unlock 释放锁(放在finally更好)

12、线程状态

13、线程之间通信:多个线程处理同一个资源,线程的任务却不同。

等待唤醒机制:
①wait、notify只能有一个在执行,所以两个线程用同步代码块包起来;
②使用的锁对象必须保持唯一;
③只有锁对象才能调用wait和notify

14、线程池
容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的过程,从而节省资源。

步骤:
①使用线程池工厂类Executors 的静态方法 newFixedThreadPool(int num) 生产一个指定线程数量的线程池。(返回的是ExecutorService接口的实现类对象,用ExecutorService接收(面向接口编程))
②创建一个类,实现Runnable 接口,重写run方法,设置线程任务。
③调用ExecutorService中的submit 方法,传递线程任务(实现类),开启线程执行run方法;
④调用ExecutorService中的shutdown 方法(不建议使用)。

  • 点赞
  • 收藏
  • 分享
  • 文章举报
蔴瓜 发布了13 篇原创文章 · 获赞 0 · 访问量 248 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: