• java多线程(内附实例:窗口售票问题、人和叉子的问题)


    java多线程的开发有两种方法:

    (1)实现Runnable接口;

    (2)继承Thread类;

    区别:

    (1)由于java中一个类只能继承一个父类,但是可以实现多个接口,所以实现Runnable接口比继承Thread更灵活。

    (2)实现Runnable接口,最终还是要用Thread(Runnable)、Thread(Runnable,String)等构造函数调用,但是此时可以多个Thread共用一个Runnable,实现资源共享(详见后面售票的实例),当然也可以使用不同的Runnable(详见后面人与叉子的实例),从这点看实现Runnable接口也比继承Thread类更灵活。

    联系:

    Thread类其内部实现如下:

    public class Thread extends Object implements Runnable,可以看出Thread类也是Runnable接口的子类;

    实例1:售票问题,假设现在有三个窗口进行售票(并发执行)。

    用实现Runnable接口的方法实现代码如下:

    package ticket2;
    
    public class ticket2 
    {
        public static void main(String []args)
        {
            Show_tickets show_ticket=new Show_tickets();
            new Thread(show_ticket,"windows1").start();
            new Thread(show_ticket,"windows2").start();
            new Thread(show_ticket,"windows3").start();
        }
    }
    class Show_tickets implements Runnable
    {
        private int tickets=10;
        public void run()
        {
            while(true)
            {
                if(tickets>0)
                {
                    System.out.println(Thread.currentThread().getName()+" showed the ticket"+tickets--);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                else
                {
                    break;
                }
            }
        }
    }

    执行结果:

    windows1 showed the ticket10
    windows2 showed the ticket9
    windows3 showed the ticket8
    windows2 showed the ticket7
    windows1 showed the ticket6
    windows3 showed the ticket5
    windows1 showed the ticket4
    windows2 showed the ticket3
    windows3 showed the ticket2
    windows2 showed the ticket1

    用继承Thread实现如下:

    package ticket1;
    
    public class ticket1 
    {
        public static void main(String []args)
        {
            new Show_tickets("window1").start();
            new Show_tickets("window2").start();
            new Show_tickets("window3").start();
        }
    }
    
    class Show_tickets extends Thread
    {
        private int tickets=10;
        private String name;
        Show_tickets(String sname)
        {
            this.name=sname;
        }
        public void run()
        {
            while(true)
            {
                if(tickets>0)
                {
                    System.out.println(name+" showed the ticket"+tickets-- );
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                else
                {
                    break;
                }
            }
        }
    }

    执行结果如下:

    window1 showed the ticket10
    window2 showed the ticket10
    window3 showed the ticket10
    window3 showed the ticket9
    window2 showed the ticket9
    window1 showed the ticket9
    window1 showed the ticket8
    window2 showed the ticket8
    window3 showed the ticket8
    window3 showed the ticket7
    window2 showed the ticket7
    window1 showed the ticket7
    window1 showed the ticket6
    window2 showed the ticket6
    window3 showed the ticket6
    window3 showed the ticket5
    window2 showed the ticket5
    window1 showed the ticket5
    window1 showed the ticket4
    window2 showed the ticket4
    window3 showed the ticket4
    window3 showed the ticket3
    window2 showed the ticket3
    window1 showed the ticket3
    window1 showed the ticket2
    window2 showed the ticket2
    window3 showed the ticket2
    window3 showed the ticket1
    window2 showed the ticket1
    window1 showed the ticket1

    可见由于方法1中Show_tickets类是被实例化之后,给三个进程共用的,所以相当于3个窗口一共有10张票大家来卖,而方法2中由于每一个Show_tickets都被实例化为一个对象,所以其中的变量tickets也就是独立的,相当于每一个窗口都有10张票。(当然方法2中也可以用static实现共享)

    实例2 人和叉子的问题,有5个人,5个叉,他们围城一圈,叉子依次摆在他们相邻的地方,只有一个人的左右手边叉子都没被用的时候,这个人才拿起叉子(左右2个都被拿起)吃饭,吃完后1秒,将叉子放下,若每个人吃一次之后就不再吃了,模仿他们吃饭的顺序。

    用实现Runnable接口的方法实现代码如下:

    package person1;
    
    public class personfork 
    {
        public static void main(String []args)
        {
            Forks fork=new Forks();
            Person person1=new Person("person1",fork);
            new Thread(person1,"0").start();;
            Person person2=new Person("person2",fork);
            new Thread(person2,"1").start();
            Person person3=new Person("person3",fork);
            new Thread(person3,"2").start();
            Person person4=new Person("person4",fork);
            new Thread(person4,"3").start();
            Person person5=new Person("person5",fork);
            new Thread(person5,"4").start();
        }
    }
    
    class Person implements Runnable
    {
        private String person_name;
        private Forks fork;
        Person(String name,Forks fork_input)
        {
            this.person_name=name;
            this.fork=fork_input;
        }
        public void run()
        {
            fork.get_fork();
            System.out.println("i am eating " + person_name);
            try 
            {
                Thread.sleep(1000);
            } catch (InterruptedException e) 
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            fork.put_fork();
        }
    }
    class Forks
    {
        private int forks[]={0,0,0,0,0};
        public synchronized void get_fork()
        {
            String thread_name=Thread.currentThread().getName();
            int num=Integer.parseInt(thread_name);
            while(1 == forks[num] || 1 == forks[(num+1)%5])
            {
                try 
                {
                    wait();
                } catch (InterruptedException e) 
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            forks[num]=1;
            forks[(num+1)%5]=1;
        }
        public synchronized void put_fork()
        {
            String thread_name=Thread.currentThread().getName();
            int num=Integer.parseInt(thread_name);
            forks[num]=0;
            forks[(num+1)%5]=0;
            notifyAll();
        }
    }

    用继承Thread实现如下:

    package personfork;
    
    
    public class personfork
    {
        public static void main(String []args)
        {
            Fork fork=new Fork();
            new Person("person1","0",fork).start(); 
            new Person("person2","1",fork).start(); 
            new Person("person3","2",fork).start(); 
            new Person("person4","3",fork).start(); 
            new Person("person5","4",fork).start(); 
        }
    }
    
    class Person extends Thread
    {
        private String person_name;
        //private String thread_name;
        private Fork fork;
        Person(String person_name1,String thread_name1,Fork fork1)
        {
            super(thread_name1);
            //person_name=person_name1;
            //fork=fork1;
            this.person_name=person_name1;
            this.fork=fork1;
        }
        public void run()
        {
            //System.out.println("I am Eating:"+person_name);
            fork.get_fork();
            System.out.println("I am Eating:"+person_name);
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            fork.put_fork();
        }
    }
    class Fork
    {
        private int forks []={0,0,0,0,0};
        public synchronized void get_fork()
        {
            int num=Integer.parseInt(Thread.currentThread().getName());
            while(1==forks[num] || 1==forks[(num+1)%5])
            {
                try {
                    wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            forks[num]=1;
            forks[(num+1)%5]=1;
        }
        public synchronized void put_fork()
        {
            int num=Integer.parseInt(Thread.currentThread().getName());
            forks[num]=0;
            forks[(num+1)%5]=0;
            notifyAll();//唤醒其他线程
        }
    }

    两种方法的结果一样基本都是5个人随机吃一遍,这里的Person是不同的5个人,所以在实现Runnable接口的方法中也并没有将其共享资源,而是放到5个不同的线程中。

  • 相关阅读:
    3、字节流输入输出实现文件的copy
    2、io的读出数据到文件中的内容(文件字节输出流)
    1、io的读取文件中的内容(文件字节输入流)
    10 linux中运行jar
    Linux 部署 iSCSI 客户端配置(Linux)
    Linux 部署 iSCSI 服务端
    Linux上使用iSCSI概述
    SSH实现免密登陆
    源码安装Python3
    Windows(受控主机)上配置
  • 原文地址:https://www.cnblogs.com/bewolf/p/5534367.html
Copyright © 2020-2023  润新知