java 多线程

实现方法

方法1 继承thread类

1)创建一个类来继承thread类

2)重写run方法 

        run 方法中编写的是线程要执行的代码

然后就可以实例化这个类 调用start方法来开启线程

方法2 实现Runnable接口

1)创建一个类来实现Runnable接口

2)重写run方法 

        run 方法中编写的是线程要执行的代码

3)创建这个类的实现类 

4)再去调用java的Thread方法

//例如创建的类是myrun 继承了runnable接口

myrun mr = new myrun();
Thread t = new Thread(mr);

然后就可以调用start方法来开启线程

方法3 实现callable接口和Future接口

                特点:可以获取线程运行的结果

1)创建一个类mycalll来实现callable接口

2)并且重写call方法    //这个方法是有返回值的 返回的就是线程运行的结果

3)创建这个mycall的对象(来表示多线程要执行的对象)

4)创建这个Future的实现类FutureTask的对象 来管理多线程的运行结果 

        将mycall的对象作为参数

5)创建线程的对象

         将FutureTask的对象作为参数

public class demo1 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        mycall mc = new mycall();
        FutureTask ft = new FutureTask<>(mc);
        Thread t = new Thread(ft);
        t.start();


        System.out.println(ft.get());
    }
}

三种实现方法的特点比较

常见成员方法

给线程设置名字

使用Thread类的 setName方法 或者是 使用Thread有参构造方法来设置

线程的优先级

在java中实现的是抢占式调度 抢占到线程的概率和优先级有关

最小是1 最大是10 默认是5 

优先级越高 抢占到cpu的概率越高

main线程

当java虚拟机启动的时候 会自动开启多条的线程

其中一条线程就是main线程,这个线程的作用就是来运行main方法的代码 

守护线程(备胎线程)

怎么开启守护线程:线程.setdeamon(true)

 当其他的非守护线程结束时,守护线程也会陆续结束

这里的陆续结束就是:

守护线程不必要强制全部执行后结束 

应用场景:

当(非守护线程)整个聊天结束,(守护线程)传输文件的这个过程也会陆陆续续的结束        

出让线程/礼让线程

怎么开启礼让线程:Thread.yield();

当一个线程执行后会出让当前cpu的执行权 让所有线程重新抢夺执行权。可以保证线程的执行尽可能的平均(只是尽可能!!仍然会出现一个线程连续执行的情况)

插入线程

怎么开启礼让线程: 

//例如存在一个aaa线程

aaa.join();
//就会把aaa线程插入到当前线程的前面 
//只有当aaa线程执行完之后才会执行当前的线程

这里说的当前线程 就是指 这个aaa.join();代码是写在哪个线程中的
比如写在main方法中 将aaa线程插入到main线程之前

线程的生命周期

线程安全

在电影院买票问题中 同时创建三个线程

1)首先会出现 三个线程卖的票是相互独立的

这个可以将票设置成static关键字,这样子三个线程的票是同一个变量。

2)但是 在这个过程中会出现 三个线程卖出的票是一样 或者多卖的这种情况

原因是sleep这个方法会将cpu的执行权放出 然后线程2,线程3就又可以进行线程的抢夺

在这个过程种,三个线程开始执行。可能出现当线程1执行完ticket++ ,没来得及执行sout,线程2却又执行了ticket++ 。导致这个静态变量变为2,然后导致三个线程输出的ticket值均为2,出现错误

综合原因是因为线程执行是具有随机性的,cpu可能会被线程抢夺

同步代码块

将操作共享数据的代码锁起来

格式:

        synchronized(锁){操作共享数据的代码}

特点 :

1)默认的锁是开启的,当一个线程进去后,锁自动关闭

2)里面的代码全部执行完毕之后,线程出来,锁自动打开

同步方法

格式:修饰符 synchronized 返回值 方法名(方法参数){}

特点 1

同步方法锁的是方法内的全部方法

特点 2

锁对象不能直接确定 非静态就是this 静态是当前类的字节码文件(.class)

Lock锁

创建一个Lock的对象调用其 lock()和unlock()方法来进行自定义锁的打开和关闭位置

(Lock是一个抽象类得创建其实现类ReentrantLock()的对象)

在使用的过程如果break跳出循环后,没有执行到unlock()方法。那么程序就不会停止

解决方法:将lock()方法后的内容用try catch 包裹 在finally中写入unlock方法

死锁

产生的四个必要条件

互斥条件:资源是独占的且排他使用,进程互斥使用资源,即任意时刻一个资源只能给一个进程使用,其他进程若申请一个资源,而该资源被另一进程占有时,则申请者等待直到资源被占有者释放。


不可剥夺条件:进程所获得的资源在未使用完毕之前,不被其他进程强行剥夺,而只能由获得该资源的进程资源释放。


请求和保持条件:进程每次申请它所需要的一部分资源,在申请新的资源的同时,继续占用已分配到的资源。


循环等待条件:在发生死锁时必然存在一个进程等待队列{P1,P2,…,Pn},其中P1等待P2占有的资源,P2等待P3占有的资源,…,Pn等待P1占有的资源,形成一个进程等待环路,环路中每一个进程所占有的资源同时被另一个申请,也就是前一个进程占有后一个进程所深情地资源。

线程池

创建了线程池 在提交任务后 如果线程池总有线程就直接调用 如果没有就创建线程(直到上线)

线程池 可以创建有上限和无上限的两种

//无上限
ExecutorService pool = Executors.newCachedThreadPool();
//上限为3
ExecutorService pool = Executors.newFixedThreadPool(3);

用sumbit来提交任务

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值