本答案为本人个人编辑,仅供参考,如果读者发现错误,请私信本人或在下方评论,一起进步!

题目链接:https://www.sxt.cn/Java_jQuery_in_action/eleven-task.html

一、 选择题

1.以下选项中可以填写到横线处,让代码正确编译和运行的是( 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();

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

A.阻塞状态

B.运行状态

C.就绪状态

D.新建状态

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

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

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

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

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

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

A.finally

B.wait( )

C.synchronized

D.notify( )

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

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

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

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

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

二、 简答题

1. 简述程序、进程和线程的联系和区别。

程序:静态概念。Java中程序包括源程序和字节码文件。

进程:执行起来的程序,动态概念。每个进程包括CPU、Data、Code

线程:是进程的一部分,是进程中一个单一的连续控制流程。

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

1⃣️继承Thread类

2⃣️实现Runnable接口

3⃣️实现Callable接口

对比

 

 

优点

缺点

继承Thread类

创建 Thread的实例来创建新的线程

存在单一继承问题

实现Runnable接口

解决单一继承问题

需要创建Thread对象

实现Callable接口

比Runnable强大,有返回值,可Throws Exception

使用麻烦

3. sleep、yield、join方法的区别?

sleep:线程暂停,进入阻塞状态,抱着资源不放,直到休眠时间满了,进入就绪状态

join:   线程暂停,进入阻塞状态,等待其他线程执行完毕再执行

yield: 线程挂起,进入就绪状态,让出CPU资源

wait:  线程等待,进入阻塞状态,资源被其他线程使用,直到notify()、notifyAll()被调用进入同步阻塞,锁可用进入就绪状态

4. synchronize修饰的语句块,如下面的代码。是表示该代码块运行时必须获得account对象的锁。如果没有获得,会有什么情况发生?

synchronized (account) {

    if(account.money-drawingNum<0){

        return;

    }

}

 

答:使用多线程时,出现多次提现问题,提现总金额大于账户总余额。

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

线程通信的方法:

   ▪ wait():线程等待,进入阻塞状态,资源被其他线程使用,直到notify()、notifyAll()被调用进入同步阻塞,锁可用进入就绪状态

   ▪  notify():唤醒阻塞状态的一个线程,使之进入就绪状态

   ▪ notifyAll():唤醒阻塞状态的所有线程,使之进入就绪状态

三、 编码题

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

package com.name.thread;

public class Web12306 {
	public static void main(String[] args) {
		Tickets ticket = new Tickets();
		new Thread(ticket,"黄牛").start();
		new Thread(ticket,"灰牛").start();
		new Thread(ticket,"黑牛").start();
	}
}
class Tickets implements Runnable{
	private int tickets = 1;
	@Override
	public void run() {
		while(true){
			if(tickets > 100) {
				break;
			}
			System.out.println(Thread.currentThread().getName()+"-->抢到了第"+tickets+++"张票");
		}
	}
}

2. 编写两个线程,一个线程打印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.name.thread;
/*	  
      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,创建打印类对象,创建两个线程类对象,启动线程*/

public class Test {
	public static void main(String[] args) {
		Printer printer = new Printer();
		NumberPrinter numP = new NumberPrinter(printer);
		LetterPrinter letP = new LetterPrinter(printer);
		numP.start();
		letP.start();
	}
}
class Printer{
	private int index = 1;
	public boolean print(int i) {
		synchronized(this) {
			if((index%3)!=0) {
				System.out.print(i);
				index++;
				return true;
			}else{
				try {
					this.notifyAll();
					this.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		return false;
	}
	public boolean print(char c) {
		synchronized(this) {
			if((index%3)==0) {
				System.out.print(c);
				index++;
				return true;
			}else{
				try {
					this.notifyAll();
					this.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		return false;
	}
}
class NumberPrinter extends Thread{
	private Printer p;

	public NumberPrinter(Printer p) {
		this.p = p;
	}
	@Override
	public void run() {
		int i = 1;
		while(i<53) {
			if(p.print(i) == true) {
				i++;
			}if(i == 53) {
				p.print(i);
			}
		}
	}
}
class LetterPrinter extends Thread{
	private Printer p;

	public LetterPrinter(Printer p) {
		this.p = p;
	}
	@Override
	public void run() {
		int i = 65;
		while(i<91) {
			char temp = (char) (i);
			if(p.print(temp) == true) {
				i++;
			}
		}
	}
}

3. 编写多线程程序,模拟多个人通过一个山洞的模拟。这个山洞每次只能通过一个人,每个人通过山洞的时间为5秒,有10个人同时准备过此山洞,显示每次通过山洞人的姓名和顺序。

package com.name.thread;
/*
 * 3. 编写多线程程序,模拟多个人通过一个山洞的模拟。这个山洞每次只能通过一个人,每个人通过山洞的时间为5秒,
 * 		有10个人同时准备过此山洞,显示每次通过山洞人的姓名和顺序。
 */
public class CrossingCave {
	public static void main(String[] args) {
		Cave cave = new Cave();
		People A = new People("A",cave);
		People B = new People("B",cave);
		People C = new People("C",cave);
		People D = new People("D",cave);
		People E = new People("E",cave);
		People F = new People("F",cave);
		People G = new People("G",cave);
		People H = new People("H",cave);
		People I = new People("I",cave);
		People J = new People("J",cave);
		A.start();
		B.start();
		C.start();
		D.start();
		E.start();
		F.start();
		G.start();
		H.start();
		I.start();
		J.start();
	}
}
/**
 * 山洞
 * @ClassName: Cave  
 * @Date 2019年10月12日 下午8:45:36
 */
class Cave{
	private  int index = 1;
	public synchronized void cross(String name) {
        try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(name+"第"+index+"个通过");
		index++;
	}
}
/**
 * 人
 * @ClassName: People  
 * @Date 2019年10月12日 下午8:45:53
 */
class People extends Thread{
	private String name;
	Cave cave;
	
	public People(String name, Cave cave) {
		super();
		this.name = name;
		this.cave = cave;
	}

	@Override
	public void run() {
		cave.cross(name);
	}	
}