多线程作业
一、填空题
1.处于运行状态的线程在某些情况下,如执行了sleep(睡眠)方法,或等待I/O设备等资源,将让出CPU并暂时停止自己的运行,进入_等待____状态。
2.处于新建状态的线程被启动后,将进入线程队列排队等待CPU,此时它已具备了运行条件,一旦轮到享用CPU资源就可以获得执行机会。上述线程是处于 就绪 状态。
3.一个正在执行的线程可能被人为地中断,让出CPU的使用权,暂时中止自己的执行,进入 等待 状态。
4.在Java中编写实现多线程应用有两种途径:一种是继承Thread类创建线程,另一种是实现 Runnable 接口创建线程。
5.在线程控制中,可以调用_____join()方法,阻塞当前正在执行的线程,等插队线程执行完后后再执行阻塞线程。
6.多线程访问某个共享资源可能出现线程安全问题,此时可以使用 __synchronized___________关键字来实现线程同步,从而避免安全问题出现,但会影响性能,甚至出现死锁。
7. 在线程通信中,调用wait( )可以是当前线程处于等待状态,而为了唤醒一个等待的线程,需要调用的方法是_____notify()_______。
8.在线程通信中,可以调用wait()、notify()、notifyAll()三个方法实现线程通信,这三个方法都是_____Object_______类提供的public方法,所以任何类都具有这三个方法。
二、选择题
-
下列关于Java线程的说法正确的是( A )。(选择一项)
A 每一个Java线程可以看成由代码、一个真实的CPU以及数据三部分组成
B. 创建线程的两种方法中,从Thread类中继承方式可以防止出现多父类的问题
C. Thread类属于java.util程序包
D. 使用new Thread(new X()).run();方法启动一个线程 -
以下选项中可以填写到横线处,让代码正确编译和运行的是( 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(); -
如下代码创建一个新线程并启动线程,问:四个选项中可以保证正确代码创建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( ) {
}
}
-
当线程调用start( )后,其所处状态为( C )。(选择一项)
A 阻塞状态
B. 运行状态
C. 就绪状态
D. 新建状态 -
下列关于Thread类提供的线程控制方法的说法中,错误的是( C )。(选择一项)
A 线程A中执行线程B的join()方法,则线程A等待直到B执行完成
B. 线程A通过调用interrupt()方法来中断其阻塞状态
C. 若线程A调用方法isAlive()返回值为false,则说明A正在执行中,也可能是可运行状态
D. currentThread()方法返回当前线程的引用 -
下列关于线程的优先级说法中,正确的是( BC )。(选择两项)
A 线程的优先级是不能改变的
B. 线程的优先级是在创建线程时设置的
C. 在创建线程后的任何时候都可以重新设置
D. 线程的优先级的范围在1-100之间 -
以下选项中关于Java中线程控制方法的说法正确的是( AD )。(选择二项)
A. join ( ) 的作用是阻塞指定线程等到另一个线程完成以后再继续执行
B. sleep ( ) 的作用是让当前正在执行线程暂停,线程将转入就绪状态
C. yield ( ) 的作用是使线程停止运行一段时间,将处于阻塞状态
D. setDaemon( )的作用是将指定的线程设置成后台线程 -
在多个线程访问同一个资源时,可以使用( A )关键字来实现线程同步,保证对资源安全访问。(选择一项)
A. synchronized
B. transient
C. static
D. yield -
Java中线程安全问题是通过关键字(C )解决的?。(选择一项)
A. finally
B. wait( )
C. synchronized
D. notify( ) -
以下说法中关于线程通信的说法错误的是( D )?。(选择一项)
A. 可以调用wait()、notify()、notifyAll()三个方法实现线程通信
B. wait()、notify()、notifyAll()必须在synchronized方法或者代码块中使用
C. wait()有多个重载的方法,可以指定等待的时间
D. wait()、notify()、notifyAll()是Object类提供的final方法,子类可以重写
三、判断题
1.进程是线程Thread内部的一个执行单元,它是程序中一个单一顺序控制流程。( F )
2.一个进程可以包括多个线程。两者的一个主要区别是:线程是资源分配的单位,而进程CPU调度和执行的单位。( F )
3.用new关键字建立一个线程对象后,该线程对象就处于新生状态。处于新生状态的线程有自己的内存空间,通过调用start进入就绪状态。( T )
4.线程可以用yield使低优先级的线程运行。( F )
5.Thread.sleep( )方法调用后,当等待时间未到,该线程所处状态为阻塞状态。当等待时间已到,该线程所处状态为运行状态。( F )
6.当一个线程进入一个对象的一个synchronized方法后,其它线程不可以再进入该对象同步的其它方法执行。( F )
四、简答题
1.简述进程和线程的联系和区别。
2.创建线程的两种方式分别是什么?各有什么优缺点。
3.请你简述sleep( )和wait( )有什么区别?
答:对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。sleep()方法导致了程序暂停执行指定的时间,让出cpu给其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。在调用sleep()方法的过程中,线程不会释放对象锁。而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态
4. Java中实现线程通信的三个方法及其作用
答:过对一个线程调用wait()函数后,线程就进入停滞状态,只有当两次对该线程调用notify或notifyAll后它才能两次回到可执行状态
五、编码题
1.设计一个多线程的程序如下:设计一个火车售票模拟程序。假如火车站要有100张火车票要卖出,现在有5个售票点同时售票,用5个线程模拟这5个售票点的售票情况。
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,创建打印类对象,创建两个线程类对象,启动线程。
六、可选题
1.设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。
要求:使用内部类实现线程,对j增减的时候不考虑顺序问题。
2.编写多线程程序,模拟多个人通过一个山洞的模拟。这个山洞每次只能通过一个人,每个人通过山洞的时间为5秒,有10个人同时准备过此山洞,显示每次通过山洞人的姓名和顺序。
多线程作业答案
一、 填空题
- 阻塞
- 就绪
- 阻塞
- Runnable
- join()
- synchronized
- notify()
- Object
二、 选择题
- A
- A
- C
- C
- C
- BC
- AD
- A
- C
- D
三、 判断题
- ×
- ×
- √
- ×
- ×
- x
四、 简答题
答案略
五、 编码题
- 设计一个多线程的程序如下:设计一个火车售票模拟程序。假如火车站要有100张火车票要卖出,现在有5个售票点同时售票,用5个线程模拟这5个售票点的售票情况。
线程类
public class SaleTicket implements Runnable {
public int total = 100;// 总票数
public int count = 0;// 票号
public void run() {
while (total > 0) {
synchronized (this) {
if (total > 0) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
count++; // 票号++
total--;// 总数减少
// 输出当前的售票窗口和票号
System.out.println(Thread.currentThread().getName()
+ "\t当前票号:" + count);
}
}
}
}
}
测试类
public class Test {
public static void main(String[] args) {
// 创建线程类对象
SaleTicket st = new SaleTicket();
// 启动5次线程
for (int i = 1; i <= 5; i++) {
new Thread(st, "售票点" + i).start();
}
}
}
- 编写两个线程,一个线程打印1-52的整数,另一个线程打印字母A-Z。打印顺序为12A34B56C….5152Z。即按照整数和字母的顺序从小到大打印,并且每打印两个整数后,打印一个字母,交替循环打印,直到打印到整数52和字母Z结束。
打印类(共享资源)
public class Printer {
private int index=1;//设为1,方便计算3的倍数
//打印数字的方法,每打印两个数字,等待打印一个字母
public synchronized void print(int i){
while(index%3==0){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(""+i);
index++;
notifyAll();
}
//打印字母,每打印一个字母,等待打印两个数字
public synchronized void print(char c){
while(index%3!=0){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(""+c);
index++;
notifyAll();
}
}
打印字母线程
public class LetterPrinter extends Thread {
private Printer p;
public LetterPrinter(Printer p){
this.p=p;
}
public void run(){
for(char c='A';c<='Z';c++){
p.print(c);
}
}
}
打印数字线程
public class NumberPrinter extends Thread {
private Printer p;
public NumberPrinter(Printer p){
this.p=p;
}
public void run(){
for(int i=1;i<=52;i++){
p.print(i);
}
}
}
测试类
public class Test {
public static void main(String[] args) {
Printer p=new Printer(); //创建打印机对象
Thread t1=new NumberPrinter(p); //创建线程对象
Thread t2=new LetterPrinter(p); //创建线程对象
t1.start(); //启动线程
t2.start(); //启动线程
}
}
六、 可选题
- 设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。
要求:使用内部类实现线程,对j增减的时候不考虑顺序问题。
public class ThreadTest { //创建类
private int j; //声明成员变量j
public static void main(String[] args) { //程序主入口
ThreadTest tt=new ThreadTest(); //创建ThreadTest的对象
//创建内部类对象
Inc inc=tt.new Inc(); //创建内部线程类对象
Dec dec=tt.new Dec(); //创建内部线程类对象
for(int i=0;i<2;i++){
// 创建线程对象,启动线程
Thread t=new Thread(inc);
t.start();
// 创建线程对象,启动线程
t=new Thread(dec);
t.start();
}
}
//实现同步对j的值加
private synchronized void inc(){
j++; //j++
System.out.println(Thread.currentThread().getName()+"-inc:"+j);
}
//实现同步对j的值减
private synchronized void dec(){
j--;
System.out.println(Thread.currentThread().getName()+"-dec:"+j);
}
//内部类
//内部类定义正确并实现run方法
class Inc implements Runnable{
@Override
public void run() {
for (int i = 0; i <100; i++) {
inc(); //调用加的方法
}
}
}
//内部类定义正确并实现run 方法
class Dec implements Runnable{
@Override
public void run() {
for (int i = 0; i <100; i++) {
dec(); //调用减的方法
}
}
}
}
- 编写多线程程序,模拟多个人通过一个山洞的模拟。这个山洞每次只能通过一个人,每个人通过山洞的时间为5秒,有10个人同时准备过此山洞,显示每次通过山洞人的姓名和顺序。
public class MulThreadTest{
public static void main(String[] args) {
//创建一个山洞(0.5分)
Tunnel tul = new Tunnel();
//创建十个过山洞线程(1.0分)
Thread p1 = new Thread(tul,"p1"); Thread p2 = new Thread(tul,"p2");
Thread p3 = new Thread(tul,"p3"); Thread p4 = new Thread(tul,"p4");
Thread p5 = new Thread(tul,"p5"); Thread p6 = new Thread(tul,"p6");
Thread p7 = new Thread(tul,"p7"); Thread p8 = new Thread(tul,"p8");
Thread p9 = new Thread(tul,"p9"); Thread p10 = new Thread(tul,"p10");
//启动十个线程0.5分
p1.start(); p2.start(); p3.start(); p4.start();
p5.start(); p6.start();
p7.start(); p8.start();
p9.start(); p10.start();
}
}
class Tunnel implements Runnable{
private int crossedNum = 0;//初始人数0.5分
public void run(){//1分
cross();
}
public synchronized void cross(){
try { //每个人通过山洞的时间为5秒(1分)
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//人数计数(0.5分)
crossedNum++;
//显示一下每次通过山洞人的姓名(1分)
System.out.println(Thread.currentThread().getName()+
"通过了山洞,这是第"+crossedNum+"个用户");
}
}