java--多线程练习题
来源:互联网 发布:java面向过程实现加法 编辑:程序博客网 时间:2024/05/17 05:16
多线程
一、判断题(T为正确,F为错误),每题1分
1.如果线程死亡,它便不能运行。(T)
2.在Java中,高优先级的可运行线程会抢占低优先级线程。(T )
3.线程可以用yield方法使低优先级的线程运行。(F)
4...程序开发者必须创建一个线程去管理内存的分配。(T)
5.一个线程在调用它的start方法,之前,该线程将一直处于出生期。(T)
6.当调用一个正在进行线程的stop( )方法时,该线程便会进入休眠状态。(F)
7.一个线程可以调用yield方法使其他线程有机会运行。(T)
8. 多线程没有安全问题(F)
9. 多线程安全问题的解决方案可以使用Lock提供的具体的锁对象操作(T)
10. Stop()方法是终止当前线程的一种状态(T)
二、选择题(不定项选择题),每题2分
1.Java语言中提供了一个▁线程,自动回收动态分配的内存。D
A.异步
B.消费者
C.守护
D.垃圾收集
2.Java语言避免了大多数的▁错误。C
A.数组下标越界
B.算术溢出
C.内存泄露
D.非法的方法参数
3.有三种原因可以导致线程不能运行,它们是▁。A B C
A.等待
B.阻塞
C.休眠
D.挂起及由于I/O操作而阻塞
4.当▁方法终止时,能使线程进入死亡状态。A
A.run
B.setPrority//更改线程优先级
C.yield//暂停当前线程的执行 执行其他线程
D.sleep//线程休眠
5.用▁方法可以改变线程的优先级。B
A.run
B.setPrority
C.yield
D.sleep
6.线程通过▁▁方法可以使具有相同优先级线程获得处理器。C
A.run
B.setPrority
C.yield
D.sleep
7.线程通过▁▁方法可以休眠一段时间,然后恢复运行。D
A.run
B.setPrority
C.yield
D.sleep
8.方法resume( )负责重新开始▁▁线程的执行。D
A.被stop( )方法停止
B.被sleep( )方法停止
C.被wait( )方法停止
D.被suspend( )方法停止
9.▁▁方法可以用来暂时停止当前线程的运行。A
A.stop( )
B.sleep( )
C.wait( )
D.suspend( )
10. 请问下列哪些类是定义在java.io包中的抽象类() A B D
A. InputStream
B. OutputStream
C. PrintStream
D. Reader
E. FileInputStream
F. FileWriter
三、简述题,每题5分
1.简述程序、进程和线程之间的关系?什么是多线程程序?
程序:程序就是一段代码,一组指令的集合,不能单独运行,需要将其加载到内存中,系统为他分配资源后才能执行(,运行时就相当于一个进程。静态的实体)
进程:进程就是系统分配资源调用的一个独立单位。是程序的一次动态执行,从加载到执行到执行完毕是一个完整的过程,并且有自己的生命周期。(动态的实体)
线程:线程依赖于进程存在,一个线程相当于进程的某个任务。
多线程程序:
一个程序运行时(进程)产生了不止一个线程,执行的路径有多条,就叫多线程
3.什么是线程调度?Java的线程调度采用什么策略?
线程调度:
对处于可运行状态的多个线程对象进行系统级的协调,防止多个线程争用有限资源而导致系统死机或者崩溃
java的线程调度采用的策略:
java 的调度策略是基于线程优先级的抢先式调度。意思就是,谁的优先级高那我就先给谁使用系统资源。
4. 如何在Java程序中实现多线程?
Java中实现多线程有三种方式,
1)定义一个类继承自Thread类,重写run方法,然后创建这个类的对象,然后通过对象调用start方法启动线程。
2)定义一个类实现Runnable接口,重写run方法,然后创建一个这个类的子类对象,然后建Thread类的对象,将子类对象作为参数进行传递,然后通过start方法启动线程。
3)线程池,使用ExecutorService、Callable、Future实现有返回结果的多线程。
4)JDK5以后新增了一个Executors工厂类来产生线程池,利用工厂类调用newFixedThreadPool方法,创建一个线程池对象,然后用线程池对象调用submit方法,传入的参数是一个实现了Callable接口的子类,重写了里面的call方法,submit方法相当于start方法,是用于启动线程的。
5.试简述Thread类的子类或实现Runnable接口两种方法的异同?
(1)继承Thread类,实现步骤
1)自定义一个类,继承自Thread类,然后重写里面的run方法
2)在主线程中创建自定义类的实例对象,通过调用start方法启动线程
(2)实现Runnable接口,步骤
1)自定义一个类实现Runnable接口并重写里面的run方法
2)在主线程中创建此类的实例对象
3)创建Thread类的实例对象,将自定义类的实例对象作为参数进行传递
4)通过start方法启动线程
这两个方法的共同点就是子类重写run方法,但是继承是重写Thread中的run方法,实现接口是Runnable中的run方法。而且都需要start来启动线程,继续是通过其创建的子类对象来调用的,接口是将子类对象作为参数来传递给Thread,然后通过Thread的对象来调用start启动的。
6. 说明缓冲流的优点和原理
缓冲流的优点提高了效率,把要操作的数据放进缓冲区,然后一次性把缓冲区的内容写到目的地,而不是写一次就往目的地写一次.
缓冲流原理:缓冲区就是内存里的一块区域,把数据先存内存里,然后一次性写入,类似数据库的批量操作,这样效率比较高。
8:在Java中wait()和sleep()方法的不同?
区别1:wait方法是在Object类中,而sleep方法是Thread类中
区别2:sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。在调用sleep()方法的过程中,线程不会释放对象锁。
而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备,获取对象锁进入运行状态。
9:Java中Runnable和Callable有什么不同?
.在实现多线程时,两种不同的方法分别用到了这两种接口,当实现Runnable接口时,重写里面的run方法拥有给虚拟机调用,在实现Callable时,重写里面的call方法用于虚拟机调用,在主线程中启动时,Runable接口是通过将其子类对象传入Thread类,然后通过Thread类的对象调用start方法实现的。而Callable接口是通过线程池对象调用submit方法启动的,然后虚拟机调用call方法实现的。其中call方法可以有返回值,run方法没有。call()可以抛出受检查的异常,比如ClassNotFoundException, 而run()不能抛出受检查的异常。
四、程序设计题
1.编写一个应用程序,在线程同步的情况下来实现“生产者―消费者”问题。
代码:主线程:
package first;
public class First {
public static void main(String[] args) {
Student s = new Student();
Get get = new Get(s);
Set set = new Set(s);
Thread th1 = new Thread(get);
Thread th2 = new Thread(set);
th1.start();
th2.start();
}
}
生产者:
package first;
public class Set implements Runnable{
private Student s;
public Set(Student s){
this.s=s;
}
private int x=0;
@Override
public void run() {
while(true){
if(x%2==0){
s.set("小明", 25);
}else{
s.set("小华", 27);
}
x++;
}
}
}
消费者:
package first;
public class Get implements Runnable{
private Student s;
public Get(Student s){
this.s=s;
}
@Override
public void run() {
while(true){
s.get();
}
}
}
共享资源:
package first;
public class Student{
private int age;
private String name;
private boolean flag;
public synchronized void set(String name,int age){
if(this.flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name=name;
this.age=age;
this.flag=true;
this.notify();
}
public synchronized void get(){
if(!this.flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(this.name+"---"+this.age);
this.flag=false;
this.notify();
}
}
2.修改上题,由于各个线程是异步运行的,因此无法预计其相对速度,为了使生产者能够不断地生产,可以使用循环缓冲区,保证有足够多的内存区保存更多的产品。(生产者——仓库——消费者)
代码:
主线程:
package two;
public class FirstUpgrade {
public static void main(String[] args) {
Box box = new Box();
Thread consumer = new Thread(new Consumer(box));
consumer.setName("消费者");
Thread producer = new Thread(new Producer(box));
producer.setName("生产者");
consumer.start();
producer.start();
}
}
生产者:
package two;
class Producer implements Runnable {
private Box box;
public Producer(Box box) {
this.box = box;
}
@Override
public void run() {
Student student = new Student(27,"小明");
box.push(student);
}
}
消费者:
package two;
class Consumer implements Runnable {
private Box box;
public Consumer(Box box) {
this.box = box;
}
@Override
public void run() {
box.pop();
}
}
仓库:
package two;
public class Box {
private Student[] students= new Student[10];
private int top = 0;
public synchronized void push(Student student) {
while (top == students.length) {
try {
wait();//仓库已满,等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//把产品放入仓库
students[top++] = student;
System.out.println(student);
notifyAll();//唤醒等待线程
}
// 消费者从仓库中取出产品
public synchronized Student pop() {
while (top == 0) {
try {
wait();//仓库空,等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//从仓库中取产品
--top;
Student p = new Student(students[top].getAge(), students[top].getName());
students[top] = null;
System.out.println(p);
notifyAll();//唤醒等待线程
return p;
}
}
共享资源:
package two;
public class Student{
private int age;
private String name;
public Student() {
super();
}
public Student(int age, String name) {
super();
this.age = age;
this.name = name;
}
public String toString() {
return "(年龄" + age + " 姓名" + name + ")";
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3 :
1)将若干个Student对象;若干个Teacher对象,写出到d:/0404/a.txt中,
2)将该文件中所有的Student对象反序列化回来,装入List,所有的Teacher对象反序列化回来装入另一个List
代码1)2)分别用两个方法实现:
主线程:
package Three;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) throws IOException, ClassNotFoundException {
write();
read();
}
private static void read() throws IOException, FileNotFoundException,
ClassNotFoundException {
ObjectInputStream r1 = new ObjectInputStream(new FileInputStream(
"e:\\0404\\a.txt"));
List<Student> list1= new ArrayList<Student>();
List<Teacher> list2= new ArrayList<Teacher>();
Student l1 = (Student)r1.readObject();
list1.add(l1);
Student l2 = (Student)r1.readObject();
list1.add(l2);
Teacher l3= (Teacher)r1.readObject();
list2.add(l3);
Teacher l4= (Teacher)r1.readObject();
list2.add(l4);
r1.close() ;
for(Student k:list1){
System.out.println(k);
}
for(Teacher k1:list2){
System.out.println(k1);
}
}
private static void write() throws IOException, FileNotFoundException {
ObjectOutputStream w1 = new ObjectOutputStream(new FileOutputStream(
"e:\\0404\\a.txt"));
Student s1 = new Student(25,"小明");
Student s2 = new Student(24,"小华");
Teacher t1 = new Teacher("狂华","012352");
Teacher t2 = new Teacher("叶秋","012467");
w1.writeObject(s1) ;
w1.writeObject(s2) ;
w1.writeObject(t1);
w1.writeObject(t2);
w1.close();
}
}
学生类:
package Three;
import java.io.Serializable;
public class Student implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private int age;;
private String name;
public Student() {
super();
}
public Student(int age, String name) {
super();
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student [age=" + age + ", name=" + name + "]";
}
}
老师类:
package Three;
import java.io.Serializable;
public class Teacher implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String name;
private String number;
public Teacher() {
super();
}
public Teacher(String name, String number) {
super();
this.name = name;
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
@Override
public String toString() {
return "Teacher [name=" + name + ", number=" + number + "]";
}
}
4:实现字符串和字节数组之间的相互转换,比如:将字符串”西部开源技术中心xbkyjszx”转换为字节数组,并将字节数组再转换回字符串!
代码:
package four;
public class Four {
public static void main(String[] args) {
String s="西部开源技术中心xbkyjszx";
byte[] bys = s.getBytes();
for(byte i:bys){
System.out.print(i);
System.out.print(" ");
}
System.out.println();
String s2=new String(bys);
System.out.println(s2);
}
}
5:用Java编程一个会导致死锁的程序,你将怎么解决?请你设计
代码:
主线程:
package five;
public class Five {
public static void main(String[] args) {
//创建线程类对象
DieLock dl1 = new DieLock() ;
DieLock dl2 = new DieLock();
//启动线程
dl1.start() ;
dl2.start() ;
}
}
两把锁:
package five;
public class MyLock {
public static final Object objA = new Object() ;
public static final Object objB = new Object() ;
}
解决A、B死锁:
package five;
public class DieLock extends Thread{
private boolean flag=true;
//重写run()方法
@Override
public void run() {
//dl1,dl2线程
if(flag){
synchronized(MyLock.objA){//锁A
System.out.println("if objA");
synchronized (MyLock.objB) {
System.out.println("if objB");
flag=false;
}
}//代码执行完毕,objA锁相当于才能被释放掉
}
if(!flag){
//dl2
synchronized (MyLock.objB) {//锁B
System.out.println("else objB");
synchronized(MyLock.objA){
System.out.println("else objA");
flag=true;
}
}
}
}
}
6:递归实现输入任意目录,列出文件以及文件夹
代码:
package six;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.ParseException;
public class Six {
public static void main(String[] args) throws ParseException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入目录:");
File srcFolder = new File(br.readLine()) ;
OutputFolder(srcFolder) ;
}
private static void OutputFolder(File srcFolder) {
//获取当前srcFolder下面的所有的文件以及文件夹的File数组
File[] fileArray = srcFolder.listFiles() ;
//对该对象非空判断
if(fileArray !=null){
//增强for遍历
for(File file :fileArray){
//继续判断file对象是否是文件夹
if(file.isDirectory()){
//继续回到目录
OutputFolder(file) ;
}else{
//不是目录,是文件,输出
System.out.println(file.getName());
}
}
System.out.println(srcFolder.getName());
}
}
}
- java--多线程练习题
- Java多线程---生产者消费者练习题
- java学习之路 之 多线程练习题
- Java基础练习题 (8)多线程
- 短实习---Java多线程(练习题)
- 多线程练习题
- 多线程练习题
- 多线程练习题
- java多线程(六) 之 店铺买卖多线程练习题
- java编程思想练习题(一)(多线程)
- C多线程练习题
- 多线程练习题(一)
- 多线程练习题(一)
- 多线程练习题(二)
- 多线程练习题(三)
- java 练习题
- JAVA练习题
- java练习题
- YTU.3131: 进阶递归之简单的整数划分问题
- environment variable 'STAGING_DIR' not defined
- c++ 简单进程交互(获取双方进程句柄)
- Hibernate+spring缓存机制配置
- ASP.NET使用JQUERY AJAX文件上传DEMO_异步文件上传例子
- java--多线程练习题
- http://blog.csdn.net/dragonxiangfu/article/details/14120785
- Gulp的安装与配置
- 刚上线的“新睿云”到底如何达到高可用?IOPS高达200000?
- 【云隐】STM32F103C8T6实现串口IAP方式升级固件
- HTTP协议:概括性知识
- 一个Activity分别加载多个layout布局文件
- 秒懂Vuejs、Angular、React原理和前端发展历史
- 人是一种复杂的动物