黑马程序员_多线程

来源:互联网 发布:淘宝客经典文案 编辑:程序博客网 时间:2024/06/09 21:09
进程与线程:进程是正在执行的程序,而线程是进程中用于控制程序执行的控制单元,其通过调用父进程中的资源执行任务。
进程可以有多个线程且其至少有一个线程。线程必须有且只有一个父进程。
当JVM启动时,就有两个线程,一个是jvm的主线程用于执行程序。另一个是jvm的垃圾回收线程用于回收系统资源。
在Java中给我们提供了线程对象及其字段与功能的是Thread。
在Thread类中定义了创建线程对象的方法(构造函数),以及.提供了会被执行的run()方法,要被执行的代码就放在run()方法里。
还定义了开启线程运行的方法(start()).
创建线程有两种方法:
第一种是直接继承Thread类
步骤:
1,继承Thread类。
2,覆盖run方法。将线程要运行的代码定义其中。
3,创建Thread类的子类对象,其实就是在创建线程,调用start方法。
public class test11 {public static void main(String[] args){Thread t1 = new T1();t1.start();}}class T1 extends Thread{public void run() {System.out.print("t1线程开启");}}
第二种是当自定义的类中继承了其它类,这就不能继承其它类,复写run()方法,这时候就让该类实现Runnable接口,复写该接口的run()方法。步骤:
1,定义了实现Runnable接口。2,覆盖接口的run方法。将多线程要运行的代码存入其中。
3,创建Thread类的对象(创建线程),并将Runnable接口的子类对象作为参数传递给Thread的构造函数。    4,调用Thread对象的start方法。开启线程。
public class test11 {public static void main(String[] args){T1 t1 = new T1();Thread thread = new Thread(t1);thread.start();}}class T1 implements Runnable{public void run() {System.out.print("t1线程开启");}}
两种方式的特点:
实现方式,因为避免了单继承的局限性,所以创建线程建议使用第二种方式。
多线程具备随机性。因为是由cpu不断的快速切换造成的。这就有可能会产生死锁问题。
死锁的产生有四个条件:
1、 互斥条件:一个资源每次只能被一个进程使用。
2、 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
3、 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
4、 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
而在代码的实现当中就只有两个关键点:
1,多线程代码中有操作共享数据。
2,多条语句操作该共享数据。
当具备两个关键点时,有一个线程对多条操作共享数据的代码执行的一部分。还没有执行完,另一个线程开始参与执行。
就会发生数据错误。
解决方法:
使用同步锁,当一个线程在执行多条操作共享数据代码时,其他线程即使获取了执行权,也不可以参与操作,这就使得这个线程所需的多个资源,在其运行完之前,不被其他线程获取。这也就破坏了上述死锁形成的第二个条件,也就不会造成死锁,但这样使用同步锁一次性就安排好所有的资源,会使得资源的利用率不高,较消耗资源。
Java就对这种解决方式提供了专业的代码。同步
同步的原理:就是将部分操作功能数据的代码进行加锁。
同步的表现形式:1,同步代码块。
2,同步函数。两者有什么不同:
同步代码块使用的锁是任意对象。同步函数使用的锁是this。
注意:对于static的同步函数,使用的锁不是this。是 类名.class 是该类的字节码文件对象,涉及到了单例设计模式的懒汉式。
同步的好处:解决了线程的安全问题。
弊端:较为消耗资源。同步嵌套后,容易死锁。
0 0
原创粉丝点击