实验八:多线程
一.实验目的
1.掌握通过Thread类和Runnable接口创建线程的方法
2.学会如何实现多线程的资源共享和通信,及如何控制线程的生命
3.在实际运用中,注意线程安全问题,掌握线程同步的方法,还应该理清程序逻辑,避免死锁
4.掌握线程优先级的概念,明白基于优先级的线程调度的基本规则
二.实验内容
2.1 巩固与理解
1.运行下面的程序,理解用创建Thread子类的方法实现多线程。 class SimpleThread extends Thread { public SimpleThread(String str) { super(str); }
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(i + \ try {
sleep((int)(Math.random() * 1000)); } catch (InterruptedException e) {} }
System.out.println(\ } }
public class TwoThreadsTest {
public static void main (String[] args) {
new SimpleThread(\ new SimpleThread(\ } }
2.运行下面的程序,理解用实现Runnable接口的方法实现多线程。 //这是一个时钟Applet,它显示当前时间并逐秒进行更新。 import java.awt.*; import java.applet.*; import java.util.*;
public class Clock extends Applet implements Runnable{ Thread clockThread; public void start( ){
1
if(clockThread==null){
clockThread=new Thread(this,\ clockThread.start(); } }
public void run(){
while(clockThread !=null){ repaint( ); try{
clockThread.sleep(1000); }catch(InterruptedException e){} } }
public void paint(Graphics g){ Date now=new Date();
g.drawString(now.getHours()+\5,10); }
public void stop(){
clockThread.stop(); clockThread=null; } }
? 编写HTML文件Clock.html:
? 运行Applet小程序,查看结果。
2.2 上机实验
1. 编写多线程程序模拟左右手轮流写字。 2. 编写一个类MyThread,它继承自Thread类:类中定义一个长整型变量delay;还定义有两个参数的构造方法,第1个参数str是String类型,通过super(str)调用父类构造方法给线程命名,第2个参数delay是长整型,用来初始化类中的变量delay。MyThread类中的run方法如下实现:循环3次,每次先在命令行输出线程第几次运行,然后休眠delay毫秒,循环结束后输出该线程结束的信息。编写应用程序TestThread.java,在其main方法中创建MyThread类的三个对象t1、t2、t3,分别指定线程名字为“线程A”、“线程B”和“线程C”,休眠时间为1000毫秒、2000毫秒、3000毫秒,并启动这三个线程,main方法的最后输出当前活动线程的数目。
3. 采用Java多线程技术编写程序,其中包括两个线程:A和B,其中A线程准备休眠一小时,B线程每隔一秒输入3句“起床”后,吵醒休眠的线程A。(25分)
2
4. 编写自定义类MyRunnable,该类实现Runnable接口,类中只有一个long类型变量delay,该类的构造函数有一个参数,用来初始化delay。类中的run方法如下实现:循环3次,每次先在命令行输出该线程第几次运行,然后休眠delay毫秒,循环结束后输出该线程结束的信息。编写应用程序TestRunnable.java,在其main方法中创建类MyRunnable类的三个对象r1、r2、r3,构造方法的参数分别指定为:1000、2000、3000。用线程类的构造方法Thread(Runnable target )创建3个线程,其参数分别为r1、r2、r3,并启动这三个线程,main方法的最后输出当前活动线程的数目。
5. 编写一个堆栈类MyStack,类中定义含5个元素的整型数组,并定义了两个同步(synchronized)方法:入栈操作方法push(int k),用来向堆栈中压入一个整数;出栈操作方法int pop( ),用来从栈顶弹出一个整数。方法push和pop中,通过wait()方法和notify()方法协调压入和弹出操作,例如,如果堆栈中没有数据则不能进行弹出操作,如果堆栈中压入的数据已有5个,则不能再进行压栈操作。此外编写两个线程子类Producer和Consumer,分别操作MyStack类对象,分别进行20次压入(压入的整数依次是1、2、…、20)和弹出操作,每次操作的结果显示再命令行界面。编写应用程序Test.java,创建一个MyStack类对象mystack,它是Producer线程和Consumer线程的共享数据源,创建和启动Producer线程和Consumer线程,对堆栈中的数据进行压入和弹出操作,观察程序的输出结果,理解线程之间的同步处理。
三.思考题
1.简述并区分程序、进程和线程三个概念。
2.线程有哪几个基本的状态?Java中线程调度遵循何种原则? 3.实现多线程可以用哪两种基本方法?将这两种方法进行比较。
四.实验报告内容
(1) 实验内容 (2) 实验目的 (3) 实验步骤 (4) 遇到的问题
(5) 实验结果与实验心得
3