设为首页 加入收藏

TOP

多线程: 线程的同步   线程间的通信   实现多线程的其它方式
2019-05-16 02:31:18 】 浏览:819
Tags:线程 同步   通信 实现 其它 方式

主要内容
[1]线程同步
[2]生产者与消费者
[3]实现多线程其它方式,线程池,线程组


23.1为什么需要线程的同步?
多线程在访问共享资源时,容易出现“数据错乱/脏数据”的情况。
同步:完成一个功能,需要N多句代码组成,这N多句代码必须一起执行完毕,才代表一个功能结束,在完成这个功能的过程中,代码不允许被“打断”,同步
同步"锁"

(1)实现同步方式
1.同步代码块

package com.bjsxt.titcket;

public class Ticetk2 implements Runnable{//Ticetk这个类具备了一个能力,多线程操作的能力
        private int ticket=5;//5张票
        @Override
        public void run() {
        
                //线程体
                for (int i = 0; i <100; i++) {
                        //同步代码块
                        synchronized (this) {//小括号中,共享资源的对象
                                if (ticket>0) {
                                        try {
                                                Thread.sleep(1000);
                                        } catch (InterruptedException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                        }
                                        System.out.println(Thread.currentThread().getName()+"卖第"+ticket+"张票");
                                        ticket--;
                                }
                        }
                }
                
        }
        
}

测试:

package com.bjsxt.titcket;

public class TestTicket {
        public static void main(String[] args) {
                //创建线程类的对象
                Ticetk2 t=new Ticetk2();  //5张票
                
                //创建三个线程代理类
                Thread t1=new Thread(t,"A窗口");
                Thread t2=new Thread(t,"B窗口");
                Thread t3=new Thread(t,"C窗口");
                
                //启动线程
                t1.start(); //for--0--100
                t2.start();//for--0--100
                t3.start();
        }
}

2.同步方法

package com.bjsxt.titcket;

public class Ticetk3 implements Runnable{//Ticetk这个类具备了一个能力,多线程操作的能力
        private int ticket=5;//5张票
        @Override
        public void run() {
                //线程体
                for (int i = 0; i <100; i++) {
                        //调用
                        saleTicket();//卖票的方法
                }
                
        }
        //同步方法  -->锁的是当前类的对象this
        private synchronized void saleTicket(){
                if (ticket>0) {
                        try {
                                Thread.sleep(1000);
                        } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()+"卖第"+ticket+"张票");
                        ticket--;
                }
        }
        
}

测试:

package com.bjsxt.titcket;

public class TestTicket {
        public static void main(String[] args) {
                //创建线程类的对象
                //Ticetk2 t=new Ticetk2();  //5张票
                Ticetk3 t=new Ticetk3(); 
                //创建三个线程代理类
                Thread t1=new Thread(t,"A窗口");
                Thread t2=new Thread(t,"B窗口");
                Thread t3=new Thread(t,"C窗口");
                
                //启动线程
                t1.start(); //for--0--100
                t2.start();//for--0--100
                t3.start();
        }
}

“锁”的是什么?共享资源对象 被锁住的对象,称为“同步监视器”
同步代码块 -->同步监视器,可以是共享资源的对象,也可以是当前类对象this
同步方法 -->同步监视器,,,只能是当前类的对象this


同步可以提高程序的安全性
过多的同步,就会产生死锁,双方都在等待对方的资源
按照“boss”的算法,计算大小,大的先获取锁

23.2生产者与消费者问题
(1)数据错乱 (旺仔矿泉水,娃哈哈小馒头) 同步

(2)重复生产和重复取走 (线程间的通信)
等待:wait()
唤醒notify(),notifyA()
以上方法均为Object类中的方法,可以被子类调用,但不能被子类重写,因为均为final修饰的方法

线程间通信的方法,只能用在同步代码块或同步方法中


sleep(...)与wait()的区别
sleep与wait都会导致线程进入阻塞状态
(1)sleep方法为Thread类中的static方法 ,wait()Object类中的final方法
(2)sleep()不会释放对象锁,wait()会释放对象锁,等待池,当notify()或notifyAll()唤醒进入锁池,就绪状态
(3)wait()等待,当被唤醒后,从wait()之后的代码开始执行
if(){
wait();
}
....... wait()之后的代码

run()方法有没有局限性? 有 ,因为如果有异常,必须处理,不允许声明
void,如果希望方法运行之后有结果怎么办?

在Java中JDK1.5开始,实现多线程的方式,有三种,实现Callable接口
call()方法的好处
(1)有返回值
(2)可以抛出异常
(3)支持泛型

package com.bjsxt.callable;

import java.util.concurrent.Callable;

public class RandomCallable implements Callable<Integer>{
        @Override
        public Integer call() throws Exception {
               
                return (int)(Math.random()*10);//0-9
        }

}

测试:

package com.bjsxt.callable;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class Test {
        public static void main(String[] args) throws InterruptedException, ExecutionException {
                //创建任务
                RandomCallable rc=new RandomCallable();
                
                //任务管理器  -->Runnable的实现类不?是,线程对象是?是
                FutureTask<Integer> ft=new FutureTask<>(rc);
                
                //创建代理类的对象
                Thread t=new Thread(ft);  //多态,接口作方法的形式参数,可以传入Runnable的任务实现类
                /**判断任务是否执行完成*/
                System.out.println("任务是否执行完毕"+ft.isDone());
                //才会执行call()方法中的代码
                t.start();
                /**在主线程中获取结果,这个时候 call()方法未必执行完,有可能执行到获取结果时,而结果还没有计算出来*/
                System.out.println("获取结果:"+ft.get()); //导致后面的代码无法执行
                
                System.out.println("任务是否执行完毕"+ft.isDone());
                
                
                
        }
}

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇没有了 下一篇vertica-->kafka-->mongodb..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目