zoukankan      html  css  js  c++  java
  • java:多线程(代理模式,Thread中的方法,Timer,生产者和消费者)

    *进程:一个正在运行的程序,进程是操作系统分配资源的基本单位,每个进行有独立的内存空间,进程之间切换开销较大。
    *线程:一个轻量级的进程,线程是任务调度的基本单位,一个进程可以有多个线程,
    * 系统没有为线程分配额外的内存空间,一个进程中的多个线程共享内存空间,线程之间切换开销较小。
    *创建线程的方式:
    * 1.继承java.lang.Thread类,并重写run方法。
    * 2.实现java.lang.Runnable接口,并重写run方法
    *线程的启动:调用start()方法进行启动线程,而非调用run方法。

    public class MyThread  extends Thread{
        public MyThread(String name){
            super(name);//调用Thread的构造方法,分配新的 Thread 对象
        }
        
        @Override
        public void run() {
            String name = getName();//获取线程的名称
            for (int i = 0; i < 10; i++) {
                System.out.println(name+"---->"+i);
            }
        }
    }
    public class MyThread2 implements Runnable{
        private String name;
        
        public MyThread2(String name){
            this.name=name;
        }
        
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println(name+"======>"+i);
            }
        }
    
    }
    public class Test {
        public static void main(String[] args) {
            MyThread thread1 = new MyThread("A");
            MyThread2 thread2 = new MyThread2("B");
            thread1.start();//启动线程A
    //        thread1.run(); //方法调用
            Thread t = new Thread(thread2);//创建代理
            t.start();//启动线程B
    //        t.run(); //方法调用
        }
    }

      代理模式:

    public interface KindWoman {
        public void makeEyes();
    }
    public class PanJinLian implements KindWoman{
        public void makeEyes(){
            System.out.println("西门大官人,大郎出去卖了炊饼,今晚约吗?");
        }
    }
    public class YanPoXi implements KindWoman{
        public void makeEyes(){
            System.out.println("西门大官人,宋押司会见梁山好汉了,今晚约吗?");
        }
    }
    /**
     * 代理
     */
    public class WangPo {
    //    PanJinLian panJinLian;
        KindWoman woman;//被代理者
        public WangPo(KindWoman woman){
            this.woman=woman;
        }
        
        public void makeEyes(){
            System.out.println("西门大官人,我是王妈妈");
            woman.makeEyes();
        }
        
        public static void main(String[] args) {
            PanJinLian panJinLian = new PanJinLian();
            WangPo wangPo = new WangPo(panJinLian); 
            wangPo.makeEyes();
            System.out.println("--------------------");
            YanPoXi yanPoXi = new YanPoXi();
            WangPo  wangPo2 = new WangPo(yanPoXi);
            wangPo2.makeEyes();
        }
    }

     Thread种的方法:

    *java.lang.Thread类
    *常用构造方法:
    * Thread()
    * Thread(String name)
    * Thread(Runnable target)
    *常用的方法:
    * getName():获取线程的名称
    * getId():获取线程的标识符Id
    * getState()返回该线程的状态。
    * getPriority() 返回线程的优先级。
    * void setPriority(int newPriority):更改线程的优先级
    * NORM_PRIORITY:默认优先级,值为5
    * MAX_PRIORITY:最高优先级,值为10
    * MIN_PRIORITY:最低优先级,值为1
    * setName(String name)改变线程名称,使之与参数 name 相同。
    * sleep(long millis) 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。
    * start():启动线程***
    * run():存放线程体中代码,不能显示调用。
    * isAlive():判断线程是否还“活”着,即线程是未终止

    public class MyThread2 extends Thread{
        private String name;//线程名称
        public MyThread2(String name){
            this.name=name;
        }
        
        @Override
        public void run() {
            System.out.println("线程"+name+"开始执行....");
            for (int i = 0; i < 10; i++) {
    //            try {
    //                Thread.sleep(1);
    //            } catch (InterruptedException e) {
    //                e.printStackTrace();
    //            }
    
                System.out.println(name+"----->"+i);
            }
            System.out.println("线程"+name+"执行结束....");
        }
        
    }
    public class MyThread extends Thread{
        private String name;//线程名称
        public MyThread(String name){
            this.name=name;
        }
        
        @Override
        public void run() {
            System.out.println("线程"+name+"开始执行....");
            
            for (int i = 0; i < 10; i++) {
    //            try {
    //                Thread.sleep(1);
    //            } catch (InterruptedException e) {
    //                e.printStackTrace();
    //            }
                System.out.println(name+"----->"+i);
                try {
                    join(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("线程"+name+"执行结束....");
        }
        
    }
    public class TestThread {
        public static void main(String[] args) {
            Thread t = Thread.currentThread();//获取当前线程
            t.setPriority(Thread.MAX_PRIORITY);//设置优先级
            t.setName("主线程");
            System.out.println("线程名称:"+t.getName());
            System.out.println("线程Id:"+t.getId());
            System.out.println("线程的优先级:"+t.getPriority());
            System.out.println("程序即将休眠1秒:");
            try {
                t.sleep(1000);//单位是毫秒.
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("当前线程是否活着:"+t.isAlive());
            System.out.println("休眠完毕!");
            
        }
    }
    public class TestMyThread {
    /*
    Join () 阻塞指定线程等到另一个线程完成以后再继续执行 
      Sleep () 使线程停止运行一段时间,将处于阻塞状态
      如果调用了sleep方法之后,没有其他等待执行的线程,这个时候当前线程不会马上恢复执行!
      yield () 让当前正在执行线程暂停,不是阻塞线程,而是将线程转入就绪状态
      如果调用了yield方法之后,没有其他等待执行的线程,这个时候当前线程就会马上恢复执行!
    */
    public static void main(String[] args) { MyThread t1 = new MyThread("线程A"); MyThread2 t2 = new MyThread2("线程B"); // t1.setPriority(1); t1.start(); // t2.setPriority(10); t2.start(); } }

    通过继承Thread类是不能用一个实例建立多个线程,故而实现Runnable接口适合于资源共享;

    当然,继承Thread类也能够共享变量,能共享Thread类的static变量;

    *模拟实现火车站售票窗口同时售票
    * 50张车票,1000人在抢票
    *Thread(Runnable target, String name) 分配新的 Thread 对象。

    public class TicketSell implements Runnable{
        private int ticket=100;//50张火车票
        
        @Override
        public void run() {
            for(int i=1;i<=1000;i++){
                Thread t = Thread.currentThread();
                String name = t.getName();
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if(ticket>0){
                    System.out.println(name+"卖出了"+(ticket--)+"号票");
                }
            }
        }
        
        public static void main(String[] args) {
            TicketSell ticketSell = new TicketSell();
            Thread t1 = new Thread(ticketSell,"A窗口");
            Thread t2 = new Thread(ticketSell,"B窗口");
            Thread t3 = new Thread(ticketSell,"C窗口");
            Thread t4 = new Thread(ticketSell,"D窗口");
            Thread t5 = new Thread(ticketSell,"E窗口");
            t1.start();
            t2.start();
            t3.start();
            t4.start();
            t5.start();
        }
        
    }

    * 模拟实现火车站售票窗口同时售票 50张车票,1000人在抢票
    * Thread(Runnable target, String name) 分配新的Thread 对象。
    * 问题:多个窗口同时售票的过程中有可能出现同一张票出售给不同人。 解决方案:利用线程同步进行解决
    * 同步:类似生活中排队,同一时刻只能有一个线程操作资源,在程序中可以通过加锁完成线程同步。
    * 同步的优点:保证数据的有效性 同步的缺点:效率较低。
    * 利用以下两种方式实现同步
    * 1.在java中可以通过synchronized关键字(同步监视器)来实现同步. 同步监视器:synchronized(obj){ obj:同步监视器
    * //代码; }
    * 2.使用同步方法(使用synchronized关键字修饰的方法)进行加锁

    public class TicketSell3 implements Runnable {
        private Integer ticket = new Integer(100);// 50张火车票
    
        @Override
        public void run() {
            for (int i = 1; i <= 1000; i++) {
                Thread t = Thread.currentThread();
                String name = t.getName();
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                sale(name);
            }
        }
        /**
         * 同步的方法:
         * @param name
         */
        public synchronized void sale(String name) {
            if (ticket > 0) {
                System.out.println(name + "卖出了" + (ticket--) + "号票");
            }
        }
    
        public static void main(String[] args) {
            TicketSell3 ticketSell = new TicketSell3();
            Thread t1 = new Thread(ticketSell, "A窗口");
            Thread t2 = new Thread(ticketSell, "B窗口");
            Thread t3 = new Thread(ticketSell, "C窗口");
            Thread t4 = new Thread(ticketSell, "D窗口");
            Thread t5 = new Thread(ticketSell, "E窗口");
            t1.start();
            t2.start();
            t3.start();
            t4.start();
            t5.start();
        }
    
    }

     eg2:

    public class BankAccount implements Runnable{
        int blance=1000;
        @Override
        public void run() {
                String name = Thread.currentThread().getName();
                System.out.println(name+"开始取款....."+blance);
                for(int i=1;i<10;i++){
                    try {
                        Thread.sleep(2);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
    //                synchronized (this) {  //利用同步监视器实现线程同步
    //                    if(blance>100){
    //                        blance=blance-100;
    //                        System.out.println(name+"取款100,余额为:"+blance);
    //                    }
    //                }
                    draw();
                }
        }
        /**
         * 利用同步方法实现线程同步
         */
        public synchronized void  draw(){
            String name = Thread.currentThread().getName();
            if(blance>100){
                blance=blance-100;
                System.out.println(name+"取款100,余额为:"+blance);
            }
        }
        
        public static void main(String[] args) {
            BankAccount  bc = new BankAccount();
            Thread t1 = new Thread(bc, "张三");
            t1.start();
            Thread t2 = new Thread(bc,"张三老婆");
            t2.start();
        }
        
    }

    *死锁:当两个线程相互等待对方释放“锁”时就会发生死锁
    *出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续
    *线程同步的优点:保证线程安全(数据安全有效)
    *线程同步的缺点:效率低,有可能造成死锁问题。

    public class TestDeadLock {
        public static void main(String[] args) {
            final DeadLock d1 = new DeadLock();
            final DeadLock d2 = new DeadLock();
            //使用匿名类创建线程
            new Thread("线程A"){
                public void run() {
                    //调用d1的m1方法是需要对d2对象进行加锁
                    d1.m1(d2);//匿名类访问外部的成员变量时,该成员必须使用final修饰
                };
            }.start();
            //使用匿名类创建线程
            new Thread("线程B"){
                public void run() {
                    //调用d2的m1方法是需要对d1对象进行加锁
                    d2.m1(d1);//匿名类访问外部的成员变量时,该成员必须使用final修饰
                };
            }.start();
        }
    }
    public class DeadLock {
        public synchronized void m1(DeadLock deadLock){
            String name = Thread.currentThread().getName();
            System.out.println(name+"进入m1方法....");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(name+"即将调用m2方法....");
            deadLock.m2();
        }
        
        public synchronized void m2(){
            String name = Thread.currentThread().getName();
            System.out.println(name+"进入m2方法....");
        }
    }

    *java.util.Timer类:定时器,一种工具,线程用其安排以后在后台线程中执行的任务
    *java.util.TimerTask类实现Runnable接口,由 Timer 安排为一次执行或重复执行的任务。
    *常用的构造方法:
    * Timer()创建一个新计时器。
    *常用的方法:
    * schedule(TimerTask task, Date time)安排在指定的时间执行指定的任务。
    * schedule(TimerTask task, long delay)安排在指定延迟后执行指定的任务。
    * schedule(TimerTask task, Date firstTime, long period)
    * 安排指定的任务在指定的时间开始进行重复的固定延迟执行。
    * schedule(TimerTask task, long delay, long period)安排指定的任务从指定的延迟后开始进行重复的固定延迟执行。

    public class MyTimerTask extends TimerTask{
        
        @Override
        public void run() {
            System.out.println("执行了MyTimerTask中的run方法。");
        }
        
        public static void main(String[] args) {
            Timer timer = new Timer();
    //        timer.schedule(new MyTimerTask(), new Date());//在当前时间执行MyTimerTask中的任务(调用其中run方法)
    //        timer.schedule(new MyTimerTask(), 5000);//延迟5000毫秒执行任务调度(调用MyTimerTask中run方法)
    //        timer.schedule(new MyTimerTask(),new Date(),2000);//从当前时间开始,每个2000毫秒做一次任务调度
            timer.scheduleAtFixedRate(new MyTimerTask(), 5000, 2000);//延迟5000毫秒,每个2000毫秒执行一次任务调度
        }
    
    }

     生产者和消费者:

    /**
     * 馒头类
     * @author Administrator
     *
     */
    public class SteamBread {
        private int id;//馒头的编号
        
        public SteamBread(int id){
            this.id=id;
        }
        
        @Override
        public String toString() {
            return "SteamBread [id=" + id + "]";
        }
        
    }
    /**
     * 盛放产品的容器(匡)
     * 1.生产者生成完产品之后将产品放入容器中,如果容器满了,停止生产并通知消费者进行消费
     * 2.消费者从容器中取出产品进行消费,如果容器空了,停止消费并通知生产者者进行生成
     *  
     * @author Administrator
     *
     */
    public class SyncStack {
        int index=0;//执行馒头的存储位置
        SteamBread[] sb = new SteamBread[6];//容器
        /**
         * 入栈:将生成者生成的馒头保存到匡中
         */
        public synchronized void push(SteamBread s){
            //判断匡是否已满
            if(index==sb.length-1){
                try {
                    this.wait();//停止生产
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            this.notify();//唤醒消费者线程进行消费
            //将馒头添加到匡中
            sb[index++]=s;
        }
        
        /**
         * 出栈:消费者从匡中获取馒头
         * @return
         */
        public synchronized SteamBread pop(){
            if(index==0){
                try {
                    this.wait();//停止消费
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            this.notify();//唤醒生成者进行生产
            this.index--;//push第n个之后,this.index++,使栈顶为n+1,故return之前要减一
            return sb[index];
        }
    }
    /*
    *
     生产者
     * @author Administrator
     *
     */
    public class Producer implements Runnable{
        SyncStack ss;//
        public Producer(SyncStack ss) {
            this.ss=ss;
        }
        
        @Override
        public void run() {
            for(int i=1;i<20;i++){
                System.out.println("生产者开始生产---->");
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                SteamBread s = new SteamBread(i);
                System.out.println("生产了:"+s);
                ss.push(s);
                
            }
        }
    
    }
    /**
     * 消费者
     * @author Administrator
     *
     */
    public class Consume implements Runnable{
        SyncStack ss;//
        public Consume(SyncStack ss) {
            this.ss=ss;
        }
        
        @Override
        public void run() {
            for(int i=1;i<20;i++){
                System.out.println("消费者开始消费---->");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                SteamBread s = ss.pop();
                System.out.println("消费者拿走了---->"+s+"号馒头");
            }
        }
    
    }
    public class Test {
        public static void main(String[] args) {
            SyncStack ss = new SyncStack();
            Producer producer = new Producer(ss);
            Consume consume = new Consume(ss);
            Thread t = new Thread(producer);
            Thread t2 = new Thread(consume);
            t.start();
            t2.start();
        }
    }
  • 相关阅读:
    软件工程系统开发课堂测试01
    java--printf
    java--局部类只能访问外包方法的final局部成员
    java--内部类实现“类的多重继承”
    java--内部类
    【转】java--final
    java--实例成员 & 静态成员
    java--方法和成员的继承,访问
    Java--格式化输出
    HDOJ 1005
  • 原文地址:https://www.cnblogs.com/kuangzhisen/p/7047417.html
Copyright © 2011-2022 走看看