• 多线程作业


    多线程作业

     

    一、    填空题

    1. 处于运行状态的线程在某些情况下,如执行了sleep(睡眠)方法,或等待I/O设备等资源,将让出CPU并暂时停止自己的运行,进入___阻塞______状态。
    2. 处于新建状态的线程被启动后,将进入线程队列排队等待CPU,此时它已具备了运行条件,一旦轮到享用CPU资源就可以获得执行机会。上述线程是处于    就绪          状态。
    3. 一个正在执行的线程可能被人为地中断,让出CPU的使用权,暂时中止自己的执行,进入      终止      状态。
    4. 在Java中编写实现多线程应用有两种途径:一种是继承Thread类创建线程,另一种是实现    Runnable         接口创建线程。
    5. 在线程控制中,可以调用_____wait_________方法,阻塞当前正在执行的线程,等插队线程执行完后后再执行阻塞线程。
    6. 多线程访问某个共享资源可能出现线程安全问题,此时可以使用____sychonazed____________关键字来实现线程同步,从而避免安全问题出现,但会影响性能,甚至出现死锁。
    7.  在线程通信中,调用wait( )可以是当前线程处于等待状态,而为了唤醒一个等待的线程,需要调用的方法是____notify__________。
    8. 在线程通信中,可以调用wait()、notify()、notifyAll()三个方法实现线程通信,这三个方法都是___object___________类提供的public方法,所以任何类都具有这三个方法。

     

    二、    选择题

    1.

    下列关于Java线程的说法正确的是(  A )。(选择一项)

     

     

     

     

    A

    每一个Java线程可以看成由代码、一个真实的CPU以及数据三部分组成

     

    B.

    创建线程的两种方法中,从Thread类中继承方式可以防止出现多父类的问题

     

    C.

    Thread类属于java.util程序包

     

    D.

    使用new Thread(new X()).run();方法启动一个线程

     

    2.

    以下选项中可以填写到横线处,让代码正确编译和运行的是(  A  。(选择一项)

     

    public class Test implements Runnable {

             public static void main(String[] args) {

                       ___________________________________

                       t.start();

                       System.out.println("main");

             }

             public void run() {

                       System.out.println("thread1!");

             }

    }

     

     

     

     

    A.

    Thread t = new Thread(new Test());

     

    B.

    Test t = new Test();

     

    C.

    Thread t = new Test();          

     

    D.

    Thread t = new Thread();

     

    3.

    如下代码创建一个新线程并启动线程,问:四个选项中可以保证正确代码创建target对象,并能编译正确的是(  C   )?(选择一项)

     

    public static void main(String[] args) {

              Runnable target=new MyRunnable( ); 

              Thread myThread=new Thread(target);

    }

     

     

     

     

    A

    public class MyRunnable extends Runnable {

             public void run( ) {

     

             }

    }

     

    B.

    public class MyRunnable extends Runnable {

             void run( ) {

     

             }

    }

     

    C.

    public class MyRunnable  implements Runnable  {

             public void run( ) {

     

             }

    }

     

    D.

    public class MyRunnable  implements Runnable  {

             void run( ) {

    }

    }

     

    4.

    当线程调用start( )后,其所处状态为(  C )。(选择一项)

     

     

     

     

    A

    阻塞状态

     

    B.

    运行状态

     

    C.

    就绪状态

     

    D.

    新建状态

     

    5.

    下列关于Thread类提供的线程控制方法的说法中,错误的是(  C  )。(选择一项)

     

     

     

     

    A

    线程A中执行线程B的join()方法,则线程A等待直到B执行完成

     

    B.

    线程A通过调用interrupt()方法来中断其阻塞状态

     

    C.

    若线程A调用方法isAlive()返回值为false,则说明A正在执行中,也可能是可运行状态

     

    D.

    currentThread()方法返回当前线程的引用

     

    6.

    下列关于线程的优先级说法中,正确的是( BD   )。(选择两项)

     

     

     

     

    A

    线程的优先级是不能改变的

     

    B.

    线程的优先级是在创建线程时设置的

     

    C.

    在创建线程后的任何时候都可以重新设置

     

    D.

    线程的优先级的范围在1-100之间

     

    7.

    以下选项中关于Java中线程控制方法的说法正确的是(  AD   )。(选择二项)

     

     

     

     

    A.

    join ( ) 的作用是阻塞指定线程等到另一个线程完成以后再继续执行

     

    B.

    sleep ( ) 的作用是让当前正在执行线程暂停,线程将转入就绪状态

     

    C.

    yield ( ) 的作用是使线程停止运行一段时间,将处于阻塞状态

     

    D.

    setDaemon( )的作用是将指定的线程设置成后台线程

     

    8.

    在多个线程访问同一个资源时,可以使用(  A  关键字来实现线程同步,保证对资源安全访问。(选择一项)

     

     

     

     

    A.

    synchronized

     

    B.

    transient

     

    C.

    static

     

    D.

    yield

     

    9.

    Java中线程安全问题是通过关键字(  C   )解决的?。(选择一项)

     

     

     

     

    A.

    finally

     

    B.

    wait( )

     

    C.

    synchronized

     

    D.

    notify( )

    10.

    以下说法中关于线程通信的说法错误的是(  B  ?。(选择一项)

     

     

     

     

    A.

    可以调用wait()、notify()、notifyAll()三个方法实现线程通信

     

    B.

    wait()、notify()、notifyAll()必须在synchronized方法或者代码块中使用

     

    C.

    wait()有多个重载的方法,可以指定等待的时间

     

    D.

    wait()、notify()、notifyAll()是Object类提供的方法,子类可以重写

     

     

    三、    简答题

    1. 创建线程的两种方式分别是什么?各有什么优缺点。

    继承Thread:

    子类重写了Thread类的run(),当调用start()时,直接找子类的run方法。

             好处:可以直接使用Thread类中的方法,代码简单。

             弊端:如果已经有了父类,就不能用这种方法。

    实现Runnable:

    构造函数中传入了Runnable的引用, 成员变量(this.target)记住了它, start()调用run()方法时内部判断成员变量(Runnable的引用:target)是否为空, 不为空编译时看的是Runnable的run(),运行时执行的是子类的run()方法

    好处:即使自己的线程有了父类也没关系,因为有了父类,也可以实现Runnable接口。

    弊端:不能直接使用Thread中的方法,需要先获取到线程对象,才能得到Thread方法,代码复杂。

    1. 请你简述sleep( )和wait( )有什么区别?

    (1)sleep(10)方法必须传入参数,参数是时间,时间到了自动醒来。wait(10)方法可以传参,也可以不传参,参数是时间,时间过后才开始等待。

    (2)sleep方法在同步代码块或同步函数中,不释放锁,wait方法在同步函数或同步代码块中,释放锁。

    1. Java中实现线程通信的三个方法及其作用。

    1、传统的线程通信。

        在synchronized修饰的同步方法或者修饰的同步代码块中使用Object类提供的wait(),notify()和notifyAll()3个方法进行线程通信。

       关于这3个方法的解释:

    (1)wait():导致当前线程等待,直到其他线程调用该同步监视器的notify()方法或notifyAll()方法来唤醒该线程。

    (2)notify():唤醒在此同步监视器上等待的单个线程。

    (3)notifyAll():唤醒在此同步监视器上等待的所有线程。

    2、使用Condition控制线程通信。

        当程序使用Lock对象来保证同步,系统不存在隐式的同步监视器,只能用Condition类来控制线程通信。

    (1)await():类似于隐式同步监视器上的wait()方法,导致当前线程等待,直到其他线程调用该Condition的signal()方法或signalAll()方法来唤醒该线程。

    (2)signal():唤醒在此Lock对象上等待的单个线程。如果所有的线程都在该Lock对象上等待,则会选择唤醒其中一个线程。选择是任意性的。

    (3)signalAll():唤醒在此Lock对象上等待的所有线程,只有当前线程放弃对该Lock对象的锁定后,才可以执行被唤醒的线程。

     

    四、    编码题

    1、设计一个多线程的程序如下:设计一个火车售票模拟程序。假如火车站要有100张火车票要卖出,现在有5个售票点同时售票,用5个线程模拟这5个售票点的售票情况。

    package com.zuikc.test;
    
    public class Test_Sale {
    
        public static void main(String[] args) {
            MyThread mt = new MyThread();
            Thread t1 = new Thread(mt, "窗口1");
            Thread t2 = new Thread(mt, "窗口2");
            Thread t3 = new Thread(mt, "窗口3");
            Thread t4 = new Thread(mt, "窗口4");
            Thread t5 = new Thread(mt, "窗口5");
            t1.start();
            t2.start();
            t3.start();
            t4.start();
            t5.start();
        }
    
    }
    
    class MyThread implements Runnable {
        private int tickets = 100;
    
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                this.sale();
            }
        }
    
        public synchronized void sale() {
            String name = Thread.currentThread().getName();
    
            if (tickets > 0) {
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
    
                    e.printStackTrace();
                }
                System.out.println(name + "卖票,tickets剩余:" + --tickets);
            }
        }
    }

    编写两个线程,一个线程打印1-52的整数,另一个线程打印字母A-Z。打印顺序为12A34B56C….5152Z。即按照整数和字母的顺序从小到大打印,并且每打印两个整数后,打印一个字母,交替循环打印,直到打印到整数52和字母Z结束。

    要求:

    1)         编写打印类Printer,声明私有属性index,初始值为1,用来表示是第几次打印。

    2)         在打印类Printer中编写打印数字的方法print(int i),3的倍数就使用wait()方法等待,否则就输出i,使用notifyAll()进行唤醒其它线程。

    3)         在打印类Printer中编写打印字母的方法print(char c),不是3的倍数就等待,否则就打印输出字母c,使用notifyAll()进行唤醒其它线程。

    4)         编写打印数字的线程NumberPrinter继承Thread类,声明私有属性private Printer p;在构造方法中进行赋值,实现父类的run方法,调用Printer类中的输出数字的方法。

    5)         编写打印字母的线程LetterPrinter继承Thread类,声明私有属性private Printer p;在构造方法中进行赋值,实现父类的run方法,调用Printer类中的输出字母的方法。

    6)         编写测试类Test,创建打印类对象,创建两个线程类对象,启动线程。

    package com.zuikc.test;
    
    public class Test {
    
        public static void main(String[] args) {
            Printer p = new Printer();
            NumberPrinter np = new NumberPrinter(p);
            LetterPrinter lp = new LetterPrinter(p);
            Thread t1 = new Thread(np);
            t1.start();
            Thread t2 = new Thread(lp);
            t2.start();
        }
    
    }
    
    class Printer {
        int index = 1;
    
        public synchronized void print(int i) throws Exception {
            if (index % 3 == 0) {
                this.wait();
            }
            this.notify();
            System.out.println(i);
            index++;
        }
    
        public synchronized void print(char c) throws Exception {
            if (index % 3 != 0) {
                this.wait();
            }
            this.notify();
            System.out.println(c);
            index++;
        }
    }
    
    class NumberPrinter extends Thread {
        private Printer p;
    
        public NumberPrinter(Printer p) {
            this.p = p;
        }
    
        @Override
        public void run() {
            for (int i = 1; i <= 52; i++) {
                try {
                    p.print(i);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    class LetterPrinter extends Thread {
        private Printer p;
    
        public LetterPrinter(Printer p) {
            this.p = p;
        }
    
        @Override
        public void run() {
            for (char c = 'A'; c <= 'Z'; c++) {
                try {
                    p.print(c);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
  • 相关阅读:
    如何与多个线程的操作epoll fd
    谈谈Runtime类中的freeMemory,totalMemory,maxMemory等几个方法
    JAVA实现实用的ZIP压缩与解压
    HornetQ
    github
    实例解析shell子进程(subshell )
    Linux Shell Scripting Tutorial (LSST) v2.0
    java中byte数组与int类型的转换(两种方式)
    inotifywait实现目录监控
    子shell的$$
  • 原文地址:https://www.cnblogs.com/songzongyuan-java/p/9414892.html
Copyright © 2020-2023  润新知