1、《Java语言程序设计基础教程》练习思考题参考答案 第7章多线程 7.1单项选择题 1、Java语言具有许多优点和特点,下列选项中,哪个反映了 Java程序并行机制的特 点?() A、安全性B、多线程 C、跨平台D、可移植 解答:B 2、Runnable接中的抽象方法是()。 A、startB、stop C、yieldD、run 解答:D 3、有以下程序段(很难) class MyThread extends Thread { public static void main(String args[]) { MyThread t = new MyThread();
2、 MyThread s = new MyThread(); t.start(); System.out.print("one."); s.start(); System.out.print("two."); } public void run() { System.out.print("Thread"); } } 则下面正确的选项是() A、编译失败 B、程序运行结果为:one.Threadtwo.Thread C、程序运行结果是:one.two.ThreaThread D、程序运行结果不确定 解答:D 5、作为类中新线程的开始点,线程的执行是从下面哪个方法开
3、始的。() A、public void start() B、public void run() C、public void int() D、public static void main(String args[]) 解答:A 6、Java中用于给对象加“互斥锁”标记的关键字是。() A、synchronized B、serialize C、transient D、static 解答:A 7. 以下哪个方法用于定义线程的执行体?( C ) A、 start()B、init() C、run()D、synchronized。 8. 以下哪个关键字可以用来为对象加互斥锁
4、 D ) A、transient B、static C、 serialize D、 synchronized 7.2填空题 7.3简答题 1、多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么? 多线程有两种实现方法,分别是继承Thread类与实现Runnable接。用Thread类的 子类创建线程对象,也就是从Thread类继承。实现Runnable接,用Thread类直接创建 线程对象。 同步的实现方面有两种,分别是synchronized wait与notify 2、创建一个新线程的方法,可以使用下面哪2种( A、继承java.lang.ThreO!,并且
5、重载run方法。 B、继承 java.lang.Runnab粪,并且重载 star方法。 C、实现java.lang.thre类d实现run方法。 D、实现 java.lang.Runnab接,实现 run方法。 E、实现 java.lang.ThreOd,实现 star方法。 解答:A,D 3、线程在它的一个完整的生命周期中有哪4种状态? 解答1: 线程在它的一个完整的生命周期中通常要经历如下的4种状态:1.创建状态(new Thread) 2.可运行状态(Runnable )不可运行状态(Not Runnabl)4.死亡状态(Dead) 解答2: 第一是创建状态。在生成
6、线程对象,并没有调用该对象的star方法,这是线程处于创 建状态。 第二是就绪状态。当调用了线程对象的star方法之后,该线程就进入了就绪状态,但 是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之 后,从等待或者睡眠中回来之后,也会处于就绪状态。 第三是运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就 进入了运行状态,开始运行run函数当中的代码。 第四是阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比 如说某项资源就绪)之后再继续运行。sleep,suspendwait等方法都可以导致线程阻塞。 第五是死亡状态。
7、如果一个线程的run方法执行结束或者调用stop方法后,该线程就 会死亡。对于已经死亡的线程,无法再使用star方法令其进入就绪。 4、线程在什么状态时,调用isAlive方法返回的值是false 5、建立线程有哪两种方法? 解答:多线程有两种实现方法,分别是继承Thread类与实现Runnable接。 6、怎样设置线程的优先级? 7、调用Thread类的什么方法可以启动一个线程?直接调用Thread类的run(方法可以 启动一个线程吗? 解答:线程调用start方法将启动线程,从新建状态进入就绪队列排队。不能直接调用 Thread类的run(方法可以启动一个线程,我们调用了 Th
8、read的run(方法,它的行为就会和 普通的方法调用一样。 8、Thread类中的start (和 run ()方法有什么区别? 解答:这个问题经常被问到,但还是能从此区分出面试者对Java线程模型的理解程度。 start方法被用来启动新创建的线程,而且start内部调用了 run(方法,这和直接调用run() 方法的效果不一样。当你调用run(方法的时候,只会是在原来的线程中调用,没有新的线 程启动,start方法才会启动新线程。 9、进程和线程的区别? 解答:进程=执行中的程序,每个进程都有自己独立的一块内存、一组系统资源。每一 个进程的内部数据和状态都是完全独立的。 线程=进
9、程中单个顺序的流控制,同类的多个线程共享一块内存、一组系统资源。线程 的运行开销很小。 一个线程是进程的一个执行流程,一个进程可以同时包含多个线程。 10、现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执 行完后执行? 解答:在T2线程的run(方法中加入代码T1.join在T3线程的run(方法中加入代码 T2.join 或者在主线程main (方法中, t1.start(); try { t1.join(); } catch (InterruptedException e) { // TODO Auto-generated catch blo
10、ck e.printStackTrace(); } t2.start(); try { t2.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } t3.start(); 11、Thread.start()Thread.run有什么区别? 解答:通过调用Thead类的start方法来启动一个线程,使之进入就绪状态,当cpu 分配时间该线程时,由JVM调度执行run(方法。直接使用run(方法叫做方法调用,不能 启动线程。
11、12、在一个对象上两个线程可以调用两个不同的同步实例方法吗? 解答:不能,因为一个对象已经同步了实例方法,线程获取了对象的对象锁。所以只 有执行完该方法释放对象锁后才能执行其它同步方法。 13、当一个同步方法已经执行,线程能够调用对象上的非同步实例方法吗? 解答:可以,一个非同步方法总是可以被调用而不会有任何问题。实际上,Java没有 为非同步方法做任何检查,锁对象仅仅在同步方法或者同步代码块中检查。如果一个方法 没有声明为同步,即使你在使用共享数据Java照样会调用,而不会做检查是否安全,所以 在这种情况下要特别小心。一个方法是否声明为同步取决于临界区访问(critia^ction a
12、ccess如果方法不访问临界区共享资源或者数据结构)就没必要声明为同步的。 14、wait方法的作用? 解答:wait方法用在synchronized方法或者synchronize块中。一般在判断语句中, 如果某条件被触发,让当前线程wait并释放对象的锁。此时可以让其他线程可以对用以对 象调用synchronize方法。直到调用notif或者notifyAl后wait的线程才有可能执行。所 以一般wait和notify是成对出现的。 15、启动一个线程是用run(还是start,()调用的时候有什么区别?(同第8题) 解答:当然是start了),当调用线程的start方法的时候,线程
13、就会进入到就绪状态。 run(方法是线程的执行入,当线程从就绪状态进入到执行状态时首先要从run(方法开始 执行。 当然,我们也是可以直接通过线程对象调用该对象的run(方法的,只是这只是一次普 通的调用,并没有启动任何一个线程。 当我们调用start方法时,是另外启动了一个线程去执行线程类的代码,并不影响主程 序的执行,但是调用run(方法的时候要等待run(方法内的代码执行完主程序才可以向下执 行 16、sleep(和 wait()有什么区别? 解答:sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会 给其他线程,但是监控状态依然保持,到时后会自动恢复
14、调用sleep不会释放对象锁。wait 是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等 待锁定池,只有针对此对象发出notify方法(或notifyAl)l后本线程才进入对象锁定池准备 获得对象锁进入运行状态。 7.4综合题 14、编写一个死锁程序? 15、在下面的代码区填入相应的代码,实现以下功能: 通过继承Thread类的子类Threadl,来创建和启动一个线程tl; 通过实现Runnable接的具体类Runner1,来创建和启动一个线程t2; public class TestThread1{ public static void
15、 main(String[] args){ /创建和启动一个线程t1,在下面写出相应代码 Thread1 t1 =new Thread1 () ; t1.start() ; /创建和启动一个线程t2在下面写出相应代码 Runner1 r1 =new Runner1() ; Thread t2 =new Thread(r1) ; t2.start() ; for(int i=0;i<1;i++){ System.out.println("Main Thread:"+ i); } } } class Runner1 implements Runnable{ public
16、void run(){ for(int i=0;i<1;i++){ System.out.println("Runner1:"+i); } } } class Thread1 extends Thread{ public void run(){ for(int i=0;i<1;i++){ System.out.println("Thread1:"+i); } } } 16、现在有T1 T2 T3三个线程,怎样保证T2在T1执行完之后执行T3在T2执行完 之后执行。请在相应区域写出实现该功能的代码。 public class JoinDemo { public st
17、atic void main(String[] args) { T1 t1=new T1("T1"); T2 t2=new T2("T2"); T3 t3=new T3("T3"); t1.start(); try { t1.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } t2.start(); try { t2.join(); } catch (InterruptedException e) { // TODO Au
18、to-generated catch block e.printStackTrace(); } t3.start(); } } class T1 extendThread{ private String name; public T1(String name) { this.name=name; } public void run()( for(int i=0;i<5;i++){ try { sleep(5); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printSt
19、ackTrace(); } System.out.println(this.n 循环" + i); } class T2 extendThread{ private String name; public T2(String name) { this.name=name; } public void run()( for(int i=0;i<5;i++){ try { sleep(5); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace();
20、} System.out.println(this.n 循环" + i); } } } class T3 extendThread( private String name; public T3(String name) { this.name=name; } public void run()( for(int i=0;i<5;i++){ System.out.println(this.n 循环" + i); } } } 第8章文件和流 8.1单项选择题 1、创建一个向文件“file. ”x追加内容的输出流对象的语句是()。 A. OutputStream
21、 out=new FileOutputStream("file.txt”); B. OutputStream out=new FileOutputStream("file.txt”, “append”); C. FileOutputStream out=new FileOutputStream("fiUe)txt”, tr D. FileOutputStream out=new FileOutputStream(new file("file.txt”)); 解答:C 2、下面哪个流类属于面向字符的输入流() A BufferedWriterB FileInputStream C O
22、bjectInputStreamD InputStreamReader 答案:D 3、以下关于File类说法错误的是(D) A. 一个File对象代表了操作系统中的一个文件或者文件夹 B. 可以使用File对象创建和删除一个文件 C. 可以使用File对象创建和删除一个文件夹 D. 当一个File对象被垃圾回收时,系统上对应的文件或文件夹也被删除 4、为了提高读写性能,可以采用什么流? ( D ) A InputStream B DataInputStream C OutputStream D BufferedInputStream 5、File类型中定义了什么方法来判
23、断一个文件是否存在?( D ) A createNewFile B renameTo C delete D exists 6、File类型中定义了什么方法来创建多级目录? ( C ) A createNewFile B exists C mkdirs D mkdir 7、(Buffered流,缓冲区)有下面代码 import java.io.*; public class TestBufferedWriter{ public static void main(String args[]) throws Exception( FileWriter fw = new Fi
24、leWriter("test.txt”); BufferedWriter bw = new BufferedWriter(fw); String str = “Hello World”; bw.write(str)) } 在处放入什么代码,能够使得test.tx文件被正确写入? A. bw.close() B. bw.flush(); C. fw.close(); 8.2填空题 1、 对于FileInputStrea来说,从方向上来分,它是输入流,从数据单位上 分,它是―一字节___流。 2、创建FileOutputStreai对象时,如果对应的文件在硬盘上不存在,则会_自动
25、创建___; 如果对应的文件在硬盘上已经存在,则―覆盖 8.3简答题 1、java中有几种类型的流? JDK为每种类型的流提供了一些抽象类以供继承,请说出 他们分别是哪些类? 解答: 字节输入流:InputStrean字节输出流:OutputStream 字符输入流:Reader,字符输出流:Writer 2、什么是java序列化,如何实现java序列化? 解答:Java对象的序列化指将一个java对象写入OI流中,与此对应的是,对象的反序 列化则从IO流中恢复该java对象。 如果要让某个对象支持序列化机制,则必须让它的类是可序列化的,为了让某个类是 可序列化的,该类必须实
26、现Serializable或Externalizab接。 8.4综合题 3、FileInputStrea流的read方法和FileRead流的read方法有何不同? 4、BufferedReade疏能直接指向一个文件对象吗? 1、( FileInputStrea和 FileOutputStrea)n利用 FileInputStrea和 FileOutputStream 完成下面的要求: 1 )用FileOutputStrean在当前目录下创建一个文件“test.txt并向文件输出“Hello World”,如果文件已存在,则在原有文件内容后面追加。 2 )用FileInputStr
27、ea读入test.txt件,并在控制台上打印出test.tx中的内容。 3 )要求用try-catch-fina处理异常,并且关闭流应放在finally中。 FileInputStream fin; FileOutputStream fon; try( fin = new FileInputStream("hello.txt"); on = new FileOutputStream("test.txt",true); fon.write("Hello World”); System.out.println( fin.read() ); fin.close(); }catch(E
28、xception e){}finally{fin.close();} 1、使用FileInputStrea类,编写一个程序,顺序读取d:/text.的文件里的内容,并 显示在控制台上面,直到文件结束为止。? import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class ep8_2 { public static void main(String[] args) { FileInputStream fis; try { fi
29、s = new FileInputStream("text.txt"); System.out.print("content of text is :"); int b; while ((b = fis.read()) 3/顺)序读取文件 textM的内容{ System.out.print((char) b); } fis.close(); } catch (FileNotFoundException e) { System.out.println(e); } catch (IOException e) { System.out.println(e); } 2、使用 File
30、InputStre磷和 FileOutputStrea类,编写一个程序,顺序读取 d:/text.txt 的文件里的内容,并将内容拷贝到d:/text.bak件? import java.io.*; public class TestFileOutputStream{ public static void main(String[] args){ int b = 0 ; FileInputStream in =null ; FileOutputStream out = null; try{ in = new FileInputStream("d:/text.txt"); out =
31、new FileOutputStream("d:/text.bak"); while((b=in.read())!=-1){ out.write(b); } in.close(); out.close(); }catch(FileNotFoundException e2){ System.out.print 找不到文件");System.exit(T); }catch(IOException e1){ System.out.printtil 件复制错误");System.exit(T); } System.out.print ^文 件已经复制"); } } 3、递归列出d
32、/jav目录下的所有子目录和文件,再显示到控制台 import java.io.* ;
public class FileList{
public static void main(String[] args){ File f = new File("d:/java") ; System.out.println(f.getName()) ; tree(f,1) ;
}
private static void tree(File f, int level){
for(int i=0;i 33、stFiles();
for(int i=0 ;i 34、main(String args[]) {
File dir = new File("c://java_work 用8F)le 对象表示一个目录
Filter filter = new Filter("j生喊一;个名为 java的过滤器
System.out.println("list java files in directory " + dir);
String files[] = dir.list (歹小毗融录dM下,文件后缀名为java的所有文件
for (int i = 0; i < files.length; i++) {
File f = new File(dir, 35、file为[剧录d//下的文件或目录创建一个File 对象
if (f.isFile伽果该对象为后缀为java的文件,则打印文件名
System.out.println("file " + f); else
System.out.println("sub directory "如如果是目/录则打印目录名
}
}
}
class Filter implements FilenameFilter { String extent;
this.extent = extent;
public boolean accept(File dir, String name) {
return 36、 name.endsWith("." + extent)回文件的后缀名
}
}
5、请编写一个程序,开启一个文本文件,一次读取其内的一行文本,令每行形成一 个String并将读出的Strin对象置于LinkedLis中,以反相次序显示出LinkedList内的所 有内容。
import java.io.*;
import java.util.*;
class exA4_2(
public static void main(String args[]) throws Exception(
LinkedList lines=new LinkedList();
BufferedRe 37、ader in=
new BufferedReader(new FileReader("exA4_2.java"));
String s;
while((s=in.readLine())!=null)
lines.add(s);
in.close();
Listiterator it=lines.listIterator(lines.size());
while(it.hasPrevious())
System.out.println(it.previous());
}
}
6、在程序中写一个"HelloJavaWorlc#好世界"输出到操作系统文件Hello.tx文件中 38、 import java.io.File;
import java.io.FileOutputStream;
public class Test5 {
/**
*在程序中写一个"HelloJavaWorld你好世界"输出到操作系统文件Hello.tx文件 中
*
*程序分析:文件写入,要用到输出流FileOutputStream
* */
public static void main(String[] args) {
//向文件D:/Hello.txt写入内容
File file = new File("D:/Hello.txt"); try {
//创建输出流
Fi 39、leOutputStream fos = new FileOutputStream(file);
/把String类型的字符串转化为byte数组的数据保存在输出流中
fos.write("HelloJavaWo 你好世界".getBytes());
fos.flush(刷//输出流
fos.closeQ关闭输出流
} catch (Exception e) { e.printStackTrace();
}
}
}
7、统计一个文件calcCharNum.txt(见附件)中字母'A'和'a出现的总次数import java.io.File;
import java.io.Fi 40、leInputStream;
public class Test7 {
/**
*统计一个文件calcCharNum.txtt见附件)中字母'A和与出现的总次数
*
*程序分析:
* 读取文件用 FileInputStream
* 一次只读一个字节(一个字母就是一个字节),当字节内容和A或a相等时,相 应的数量加1
* */
public static void main(String[] args) { try {
/添加文件路径
File file = new File("D:/java/calcCharNum.txt");
//创建文件读取流
FileInput 41、Stream fis = new FileInputStream(file);
int numA = 0;字母A的数量
int numa = 0制母a的数量
int len =每次读取的字节数量
while ((len=fis.read())!= -1) {
/统计字母a的数量
if (new String((char)len+"").equals("a")) { numa++;
}
/统计字母A的数量
if (new String((char)len+"").equals("A")) { numA++;
}
}
/打印出文件内字母的数量
System.out.pri 42、ntln的'数量是:"+numa);
System.out.println 的数量是:"+numA);
System.out.println和"A 出现的总次数:"+(numA+numa));
fis.close关闭输入流
} catch (Exception e) { e.printStackTrace();
}
}
}
8、输入两个文件夹名称,将A文件夹内容全部拷贝到B文件夹,要求使用多线程来操 作。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream 43、
import java.io.IOException;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.xykj.lesson2.FileUtils;
public class Test12 {
/*
*输入两个文件夹名称,将A文件夹内容全部拷贝到B文件夹,要求使用多线程 来操作。
*
*程序分析:
* 1.拷贝文件里面的东西,要 44、分析的东西还是蛮多的,要先建文件夹再拷贝里面 的东西,而且要一层层的来搞
* 2这里也需要文件遍历工具,直接调用第二题的工具类,不再重写
* 3多线程的使用,可以直接在方法里面直接新建线程
* 4对整个文件夹进行复制文件夹分隔符可以用\或/,其他的都是不对的
*所有其中还对输入的分割符进行了替换
*这题看起来比较长,分开看其实也不长
* */
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.printinj"制的文件夹:");
String 45、 fromDir = scanner.nex 接收输入
System.out.printinj"制到哪里去:");
String toDir = scanner.nex接;收输入
〃把输入的地址转化为File类型
File fromFile = new File(fromDir);
File toFile = new File(toDir);
//新建线程
new Thread(){
/里面做实际操作
public void run() {
//判断如果要复制的是文件,直接复制就可以了
if (fromFile.isFile()) {
System.out.printl 46、J复制 单个文件");
copy(fromFile, toFile);
} else {
//要复制文件夹
〃要防止一种无法进行的复制:比如说,要把复制的文件复制 到自己的子文件夹里面
〃举个例子:把D:/java/j文件夹复制到D:/java/jsp文件夹里 面,
//这会导致子文件不断增加的同时,而父文件也要不断增加, 的一个死循环
〃如果反过来,就没事,相当于只是简单的覆盖而已
〃具体实现就是看:目的地地址包含复制的文件夹地址,就不
允许操作
if (toDir.replace("/", "\\").toLowerCase() .startsWith(fromDir. 47、replace("/", "\\").toLowerCase())) { return;
}
〃复制文件(包括文件和文件夹)操作
〃先获取所有的文件(包括文件和文件夹)
List 48、utePath(); 〃把原来的文件路径换成新的文件路径 StringtoName = name.replace(fromFile.getParenoDir + "/");
System.out.println(name变+成"了" + toName);
//如果是文件夹,直接创建 if (file.isDirectory()) { new File(toName).mkdirs();
} else {
〃如果是文件,在线程里面复制 threadPool.execute(new Runnable() { ^Override public void run() {
File copyF 49、ile = new File(toName);
〃先要有父文件夹 copyFile.getParentFile().mkdirs();
//开始复制文件 copy(file, copyFile); }
});
}
scanner.close();
);
}.start(开始线程
}
/复制文件的操作
public static void copy(File fromFile, File toFile) {
〃定义一个输入流
FileInputStream fis = null;
〃定义一个输出流
FileOutputStream fos = null;
try { 50、
//把复制地址的File封装后赋值给输入流对象
fis = new FileInputStream(fromFile);
//把目的地的File封装后复制给输出流的对象
fos = new FileOutputStream(toFile);
//创建一个容量,
byte[] buf = new byte[1024];
//每次读取/写入的字节长度
int len = 0;
//边读边写
while ((len = fis.read(buf)) !判断是否还能读到数据
//把输入放到输出流里面
fos.write(buf, 0, len);
}
} catch (E






