文档库 最新最全的文档下载
当前位置:文档库 › 1774143105-张强第5章第11次 多线程实验报告

1774143105-张强第5章第11次 多线程实验报告

1774143105-张强第5章第11次 多线程实验报告
1774143105-张强第5章第11次 多线程实验报告

第五章多线程

实验5-1 继承Thread类创建多线程

一、实验描述

1、考核知识点

名称:继承Thread类创建多线程

2、练习目标

掌握如何通过继承Thread类实现多线程的创建。

掌握Thread类中run()方法和start()方法的使用。

3、需求分析

在程序开发中,会遇到一个功能需要多个线程同时执行才能完成的情况。这时,可以通过继承线程类Thread,并重写Thread类中的run()方法来实现。为了让初学者熟悉如何创建多线程,在实验中将通过继承Thread类方式创建线程,并实现多线程分别打印0~99的数字的功能。

4、设计思路(实现原理)

1)自定义一个类Demo,使其继承Thread类。

2)在Demo类中重写run()方法,在run()方法内编写一个for循环,循环体内打印:“Demo:”+

当前循环次数。

3)编写测试类Example01,在Example01类的main()方法中,创建一个Demo对象,并执行其

start()方法,接着编写一个for循环,循环体内打印:“main:”+当前循环次数。

二、实验实现

class Demo extends Thread {

public void run() {

for (int x = 0; x < 100; x++) {

System.out.println("Demo:"+x);

}

}

}

public class Example01{

public static void main(String[] args) {

Demo d = new Demo();

d.start();

for(int x=0; x<100; x++){

System.out.println("main:"+x);

}

}

}

运行结果如图5-1所示。

图5-1运行结果

三、实验总结

1、通过继承Thread类,并重写Thread类中的run()方法可以实现多线程。

2、Thread类中,提供的start()方法用于启动新线程,线程启动后,系统会自动调用run()方法。

3、main()方法中有一条主线程在运行。

实验5-2 实现Runnable接口创建多线程

一、实验描述

1、考核知识点

名称:实现Runnable接口创建多线程

2、练习目标

掌握如何通过实现Runnable接口方式创建多线程。

掌握如何使用Thread类的有参构造方法创建Thread对象。

3、需求分析

在Java中只支持单继承,因此通过继承Thread类创建线程有一定的局限性,这时可以使用另一种方式,即实现Runnable接口来创建线程。通过这种方式需要在Thread(Runnable target)的构造方法中,传递一个实现了Runnable接口的实例对象。接下来在实验中将通过实现Runnable 接口方式创建线程,并实现多线程分别打印0~99的数字的功能。

4、设计思路(实现原理)

1)自定义一个类Demo,使其实现Runnable接口。

2)在Demo类中覆写run()方法,在方法编写一个for循环,循环体内打印:当前线程名称:+

当前循环次数。

3)编写测试类Example02,在Example02类的main()方法中,创建一个Demo对象,利用Thread

(Runnable target)构造方法创建2个线程对象,分别命名为“蜘蛛侠”和“钢铁侠”,并执

行线程对象的start()方法,同时编写for循环,循环内打印“main:”+当前循环次数。二、实验实现

class Demo implements Runnable {

public void run() {

for(int x=0; x<100; x++){

System.out.println(Thread.currentThread().getName()+":"+x);

}

}

}

public class Example02 { public static void main(String[] args) { Demo d = new Demo();

Thread t1 = new Thread(d,"蜘蛛侠"); Thread t2 = new Thread(d,"钢铁侠"); t1.start(); t2.start();

for (int x = 0; x < 100; x++) { System.out.println("main:" + x);

}

}

}

运行结果如图5-2所示。

图5-2

运行结果

三、实验总结

1、可以把实现了Runnable 接口并重写run()方法的实例对象,作为Thread 有参构造方法的参数来创建多线程程序。

2、使用Thread 类的构造方法Thread(Runnable target, String name)创建线程对象时,还可以给线程指定新名称。

3、思考一下:既然有了继承Thread 类的方式,为什么还要有实现Runnable 接口的方式?

a) 可以避免由于Java 的单继承带来的局限性。在开发中经常碰到这样一种情况,就是使用一个已经继承了某一个类的子类创建线程,由于一个类不能同时有两个父类,所以不能用继承Thread 类的方式,那么就只能采用实现Runnable 接口的方式。 b) 实现接口的方式,适合多个相同程序代码的线程去处理同一个资源的情况,把线程同程序代码、数据有效的分离,很好的体现了面向对象的设计思想。例如:一个售票程序继承了Thread 类,在售票时启动了多个售票程序,但他们不是同一个对象,数据没有共享,这样就会出现票数重复出售的情况;而当售票程序实现Runnable 接口后,多个线程运行同一个售票程序,实现了票数共享的好处。

实验5-3 设置后台线程

一、实验描述

1、考核知识点

名称:后台线程

2、练习目标

了解后台线程的生命周期

掌握如何将线程设置为后台线程

3、需求分析

默认情况下,新创建的线程都是前台线程,若想使前台线程变为后台线程,可以使用setDaemon(true)方法实现,为了让初学者熟悉后台线程,实验中将通过设置一个后台线程并演示后台线程和程序结束之间的关系。

4、设计思路(实现原理)

1)自定义一个类Watcher,使其实现Runnable接口。

2)在Watcher类中覆写run()方法,在方法内编写一个for循环,循环体内打印:线程名称+循环

次数。

3)编写测试类Example03,在Example03类的main()方法中,创建一个Watcher对象,利用Thread

(Runnable target)构造方法创建线程对象并命名,将线程设置为后台线程,执行该线程的

start()方法,接着编写一个for循环,循环内打印循环次数。

二、实验实现

class Watcher implements Runnable {

public void run() {

for (int x = 0; x < 1000; x++) {

System.out.println("我是"+Thread.currentThread().getName() +"守护者,"+"我在守护雅典娜"+x);

}

}

}

public class Example03 {

public static void main(String[] args) {

Watcher watcher = new Watcher();

Thread t = new Thread(watcher,"星矢");

t.setDaemon(true);

t.start();

for (int i = 3; i >0; i--) {

System.out.println("我是雅典娜女神,我马上死了!"+i);

if(i==1){

System.out.println("我是雅典娜女神,我死了!");

}

}

}

}

运行结果如图5-3所示。

图5-3

运行结果

三、实验总结

1、在多线程程序中,一旦前台线程(例如主线程)结束,后台线程也就结束了。

2、要将某个线程设置为后台线程,该线程的setDaemon()方法必须在start()方法之前调用,否则会引发IllegalThreadStateException 异常。

实验5-4 线程的优先级

一、实验描述

1、 考核知识点

名 称:线程的优先级

2、 练习目标

了解线程中优先级的概念和作用 掌握设置线程优先级的方法

掌握线程设置优先级方法中的三个静态常量

3、 需求分析

在应用程序中,如果要对线程进行调度,最直接的方式就是设置线程的优先级。这时,可以通过线程的setPriority()方法来设置线程优先级别,实现对线程的调度功能。为了让初学者掌握线程的优先级,在实验中创建3个线程,分别为它们设置不同的优先级来演示不同优先级线程的调度。

4、 设计思路(实现原理)

1) 自定义一个类Demo ,使其实现Runnable 接口。

2) 在Demo 类中重写run()方法,在方法内编写一个for 循环,循环体内打印:线程名称+循环

次数。

3) 编写测试类Example04,在Example04类的main()方法中,创建一个Demo 对象,利用Thread

的构造方法创建三个线程对象并命名,使用setPriority()方法将其中两个线程的优先级设为最大和最小,最后开启三个线程的start()方法。

二、实验实现

class Demo implements Runnable {

public void run() {

for (int x = 0; x < 5; x++) {

System.out.println(Thread.currentThread().getName() + "---" + x);

}

}

}

public class Example04 {

public static void main(String[] args) {

Demo d = new Demo();

Thread t1 = new Thread(d,"杨过");

Thread t2 = new Thread(d,"岳不群");

Thread t3 = new Thread(d,"金龙");

//设置线程的优先级

t3.setPriority(Thread.MAX_PRIORITY);

t2.setPriority(1);

t1.start();

t2.start();

t3.start();

}

}

运行结果如图5-4所示。

图5-4运行结果

三、实验总结

1、在多线程程序中,可以通过设置线程的优先级别来控制线程获得CPU执行的几率。

2、线程的优先级用1~10之间的整数来表示,数字越大优先级越高。也可以使用静态常量表示线程的

优先级,如:MAX_PRIORITY、MIN_PRIORITY、NORM_PRIORITY。

3、虽然Java中提供了10个线程优先级,但是这些优先级需要操作系统的支持,不同的操作系统对优

先级的支持是不一样的,不能很好的和Java中线程优先级一一对应,因此,在设计多线程应用程序时,

其功能的实现一定不能依赖于线程的优先级,而只能把线程优先级作为一种提高程序效率的手段。实验5-5 线程休眠

一、实验描述

1、考核知识点

名称:线程休眠

2、练习目标

了解线程休眠的概念和作用

掌握如何使用sleep(long millis)方法使线程休眠

3、需求分析

如果希望人为地控制线程,使正在执行的线程暂停,将CPU让给别的线程。这时,可以使用静态方法sleep(long millis),该方法可以让当前正在执行的线程暂停一段时间,进入休眠等待状态。为了让初学者更好地掌握线程休眠,实验中将启动三个线程共同出售10张票来演示线程休眠及休眠引发的结果。

4、设计思路(实现原理)

1)自定义一个类Ticket,使其实现Runnable接口,并在该类中创建int类型私有属性tickets,

赋初值为10。

2)在Ticket类中重写run()方法,在方法内编写一个while循环。循环体内判断ticket值,当大

于0时,使用sleep(long millis)方法使线程休眠1秒钟,并打印:当前线程名称+“正在出售

第”+循环次数;否则结束循环。每执行一次while循环,tickets值减一。

3)编写测试类Example05,在Example05类的main()方法中,创建一个Ticket对象,利用Thread

的构造方法创建三个线程对象并命名,并开启三个线程的start()方法。

二、实验实现

class Ticket implements Runnable {

private int tickets = 10;

public void run() {

while (true) {

if (tickets > 0) {

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()

+ "正在出售第" + (tickets--) + "张票");

}

}

}

}

public class Example05 {

public static void main(String[] args) {

Ticket tr = new Ticket();

Thread t1 = new Thread(tr);

Thread t2 = new Thread(tr);

Thread t3 = new Thread(tr);

t1.setName("窗口1");

t2.setName("窗口2");

t3.setName("窗口3");

t1.start();

t2.start();

t3.start();

}

}

运行结果如图5-5所示。

图5-5运行结果

从运行结果可以看出,当程序启动后,“窗口1”、“窗口2”、“窗口3”线程共同出售tikcets,但是最后“窗口1”出售了第0张票、“窗口3”出售了第-1张票,从中可以推断当tickets=1时,某一个线程进入if分支语句后,线程休眠了1秒。在此期间,tickets的值依然为1,其他两个线程也顺利进入了到if分支语句中,当线程休眠时间结束后,三个线程分别操作了ticket值,所以造成了tickets值为负数。

三、实验总结

1、sleep(long millis)方法声明抛出InterruptedException异常,因此在调用该方法时应该捕获异常,或

者声明抛出该异常。

2、sleep()是静态方法,只能控制当前正在运行的线程休眠,而不能控制其它线程休眠。当休眠时间结

束后,线程就会返回到就绪状态,而不是立即开始运行。

实验5-6 线程让步

一、实验描述

1、考核知识点

名称:线程让步

2、练习目标

了解线程让步的概念和作用

掌握设置线程让步的方法

3、需求分析

在校园中,我们经常会看到同学互相抢篮球,当某个同学抢到篮球后就可以拍一会,之后他会把篮球让出来,大家重新开始抢篮球,这个过程就相当于Java程序中的线程让步。在多线程程序中,可以通过线程的yield()方法将线程转换成就绪状态,让系统的调度器重新调度一次,达到线程让步的目的。实验中将在一个多线程程序中,通过yield()方法对其中一个线程设置线程让步来演示。

4、设计思路(实现原理)

1)自定义一个类Demo,使其实现Runnable接口。

2)在Demo类中覆写run()方法,在方法内编写一个for循环,循环体内,先执行线程让步的方

法yield(),然后输出打印:线程名称+循环次数。

3)编写测试类Example06,在Example06类的main()方法中,创建一个Demo对象,利用Thread

的构造方法创建两个线程对象,并执行线程对象的start()方法,同时编写for循环,循环内打

印“main:”+当前循环次数。

二、实验实现

class Demo implements Runnable{

public void run(){

for(int x = 0 ; x < 5 ; x++){

Thread.yield();

System.out.println(Thread.currentThread().getName()+"..."+x);

}

}

}

public class Example06 {

public static void main(String[] args)throws Exception {

Demo d = new Demo();

Thread t0 = new Thread(d);

Thread t1 = new Thread(d);

t0.start();

t1.start();

for(int x = 0 ; x<5 ; x++){

System.out.println("main..."+x);

}

}

}

运行结果如图5-6所示。

图5-6运行结果

三、实验总结

1、在多线程程序中,可以通过设置线程让步,让系统的调度器重新调度一次CPU的分配。

2、线程让步和线程休眠是不一样的,线程让步不会阻塞该线程,它只是将线程转换成就绪状态,而

线程休眠,是让线程在一定时间内进入休眠等待状态,到达时间后线程再转换成就绪状态。

实验5-7 线程插队

一、实验描述

1、考核知识点

名称:线程插队

2、练习目标

了解线程插队的概念和作用

掌握线程插队方法的使用

3、需求分析

在火车站买票的时候,有的乘客着急赶火车,会插到队伍前面先买车票,其他乘客再买票。

那么在多线程程序中,也可以通过线程插队,让插队的线程先执行完,然后本线程才开始执行。

在实验中将通过使用join()方法来演示线程插队。

4、设计思路(实现原理)

1)自定义一个类Demo,使其实现Runnable接口。

2)在Demo类中覆写run()方法,在方法内编写一个for循环,循环体内打印:线程名称+循环

次数。

3)编写测试类Example07,在Example07类的main()方法中,创建一个Demo对象,利用Thread

的构造方法创建两个线程对象,分别命名“排队队员”和“插队队员”,然后编写两个线程

对象的start()方法,然后调用“插队队员”线程的join()方法。

二、实验实现

class Demo implements Runnable { public void run() {

for (int x = 0; x < 5; x++) { System.out.println(Thread.currentThread().getName() + "---" + x);

}

}

}

public class Example07 { public static void main(String[] args) { Demo jd = new Demo(); Thread t1 = new Thread(jd); Thread t2 = new Thread(jd); t1.setName("排队队员"); t2.setName("插队队员"); t1.start(); t2.start(); try { t2.join();

} catch (InterruptedException e) { e.printStackTrace();

}

}

}

运行结果如图5-7所示。

图5-7

运行结果

三、实验总结

1、线程插队,可以让插队的线程先执行完,然后本线程才开始执行。

2、使用线程插队join()方法时,需要抛出InterruptedException 异常。

实验5-8 同步代码块的使用

一、实验描述

1、考核知识点

名称:同步代码块

2、练习目标

掌握同步代码块作用

掌握同步代码块的使用方法

掌握同步代码块中锁对象的使用

3、需求分析

生活中,会遇到两人上洗手间的问题,甲使用洗手间的时候会锁上门,乙看到门锁上了,就需要等甲使用完后再使用的。那么在多线程程序中,可以通过将共享资源放在同步代码块内来实现多个线程同步处理共享资源的问题。本实验将通过两个线程共享资源来演示同步代码块的使用。

4、设计思路(实现原理)

1)自定义一个类Demo,使其实现Runnable接口。

2)在Demo类中覆写run()方法,在方法内编写synchronized同步代码块,在进入同步代码块时,

打印线程名称,然后编写一个for循环,循环体内打印:运行线程名称+循环次数。当循环次

数等于3时,跳出循环。

3)编写测试类Example08,在Example08类的main()方法中,创建一个Demo对象,利用Thread

的构造方法创建两个线程对象,分别命名“张三”和“李四”,执行两个线程的start()方法。

二、实验实现

class Demo implements Runnable {

private Object obj = new Object();

public void run() {

synchronized (obj) {

System.out.println(Thread.currentThread().getName()

+ "进入洗手间,门以锁上");

for (int i = 1; i < 10; i++) {

System.out.println(Thread.currentThread().getName()

+ "正在使用洗手间"+i);

if (i == 3) {

System.out.println(Thread.currentThread().getName()

+ "用完,准备出去,锁打开");

break;

}

}

}

}

}

public class Example08 {

public static void main(String[] args) { Demo d = new Demo();

Thread t1 = new Thread(d, "张三"); Thread t2 = new Thread(d, "李四"); t1.start(); t2.start();

}

}

运行结果如图5-8所示。

图5-8

运行结果

三、实验总结

1、同步代码块中的锁对象可以是任意类型的对象,但多个线程共享的锁对象必须是唯一的。

2、锁对象的创建代码不能放到run()方法中,否则每个线程运行到run()方法都会创建一个新对象,这样每个线程都会有一个不同的锁,每个锁都有自己的标志位。线程之间便不能产生同步的效果。

实验5-9 同步代码块嵌套造成死锁

一、实验描述

1、 考核知识点

名 称:死锁

2、 练习目标

了解什么是死锁和造成死锁的原因

3、 需求分析

在编写多线程程序中,经常出现多个同步代码块嵌套的情况,而此时如果没有控制好锁对象的一致性就会出现死锁现象,接下来,在实验中通过同步代码块之间的互相嵌套来演示线程死锁。

4、 设计思路(实现原理)

1) 自定义一个类DieLock ,使其继承Thread 。

2) 在DieLock 类中创建两个静态常量objA 、objB ,分别是a 锁、b 锁。然后创建一个boolean

类型的私有属性flag 作为标示符,并编写DieLock 的构造方法

3) 重写run()方法,在方法内首先判断flag 的值。当flag 值为true 时,分别以objA 和objB 为

锁对象,编写两个嵌套的同步代码块,并在同步代码块中打印flag值和锁对象名称;当flag

为值为false时,编写flag为false时的代码,只是把锁对象的顺序更换一下。

4)编写测试类Example09,在Example09类的main()方法中,利用DieLock的构造方法,创建

两个DieLock对象,传入的flag值分别为true和false,执行两个线程的start()方法。二、实验实现

class DieLock extends Thread {

private boolean flag;

static Object objA = new Object();

static Object objB = new Object();

public DieLock(boolean flag) {

this.flag = flag;

}

public void run() {

if (flag) {

synchronized (objA) {

System.out.println("true -- objA");

synchronized (objB) {

System.out.println("true -- objB");

}

}

} else {

synchronized (objB) {

System.out.println("false -- objB");

synchronized (objA) {

System.out.println("false -- objA");

}

}

}

}

}

public class Example09 {

public static void main(String[] args) {

new DieLock(true).start();

new DieLock(false).start();

}

}

运行结果如图5-9所示。

图5-9运行结果

当两个线程的同步代码块彼此拿着对方需要的锁时,程序不会停止,但会一直“卡顿”,这种现象就是“死锁”现象。

实验5-10 多线程通信

一、实验描述

1、考核知识点

名称:多线程通信

2、练习目标

掌握如何解决线程通信中的共享资源的安全问题

3、需求分析

一条生产线的上下两个工序,它们必须以规定的速率完成各自的工作,才能保证产品在流水线中顺利的流转。在多线程的程序中,上下工序可以看作两个线程,这两个线程之间需要协同完成工作,就需要线程之间进行通信。了让初学者掌握多线程通信,实验中将通过生产和消费鼠标这两个过程的多线程协调来演示。

4、设计思路(实现原理)

1)创建一个产品类Product,该类有三个属性分别是:产品名称name,产品数量count,和一个

boolean类型的标示量flag。当flag值为false时,说明产品未生产,当flag值为true时,说明产品已生产。

2)在Product类中编写一个同步方法set(),每次调用set()方法时,表示要生成一个产品。在set()

方法中,编写一个while循环,当flag值为true时,调用该线程的wait()方法,让线程等待。在while循环体外,count值递增,并打印当前线程名称和产品名称及数量,最后将flag值设为true,并唤醒所有的线程。

3)在Product类中编写一个同步方法get(),每次调用get()方法时,表示要消费一件产品。在get()

方法中,编写一个while循环,当flag值为false时,调用该线程的wait()方法,让线程等待。在循环体外,打印当前线程名称和被消费的产品名称和个数。最后将flag值设为false,并唤醒所有的线程。

4)编写一个生产类Producter,该类定义了一个Product类型的成员变量和有参构造方法,构造

方法中的参数用于为Product对象赋值,并且Producter类实现了Runnable接口。

5)重写Runnbale接口的run()方法,在run()方法内,执行死循环,每循环一次调用Product对

象的set()方法。

6)编写一个消费类Customer,该类定义了一个Product类型的成员变量和有参构造方法,构造

方法中的参数用于为Product对象赋值,并且Customer类实现了Runnable接口。

7)重写Runnable接口的run()方法,在run()方法内,执行死循环,每循环一次就调用producet

对象的get()方法。

8)编写一个测试类Example10,创建一个Product对象,生产者和消费者分别利用product对象

创建各自的对象,最后使用Thread类创建2个“生产者”线程和2个“消费者”线程,并执行四个线程的start()方法。

//定义产品类

class Product {

private int count;// 产品的计数器

private String name;

private boolean flag = false;

// set生产的方法

public synchronized void set(String name) {

while (flag == true) {

try {

this.wait();

} catch (Exception e) {

}

}

https://www.wendangku.net/doc/773926670.html, = name + count++;// 鼠标0

System.out.println(Thread.currentThread().getName() + "生产了第"

+ https://www.wendangku.net/doc/773926670.html, + "个鼠标===========");

flag = true;

this.notifyAll();

}

// get消费的方法

public synchronized void get() {

while (flag == false) {

try {

this.wait();

} catch (Exception e) {

}

}

System.out.println(Thread.currentThread().getName() + "消费了第"

+ https://www.wendangku.net/doc/773926670.html, + "个鼠标");

flag = false;

this.notifyAll();

}

}

// 生产者类

class Producter implements Runnable {

private Product p;

Producter(Product p) {

this.p = p;

}

public void run() {

while (true) {

p.set("鼠标");

}

}

}

// 消费者类

class Customer implements Runnable { private Product p; Customer(Product p) { this.p = p; }

public void run() { while (true) { p.get(); }

}

}

public class Example10 { public static void main(String[] args) { Product p = new Product(); Producter pr = new Producter(p); Customer cr = new Customer(p); Thread t1 = new Thread(pr); Thread t2 = new Thread(pr); Thread t3 = new Thread(cr); Thread t4 = new Thread(cr); t1.start(); t2.start(); t3.start(); t4.start(); }

}

运行结果如图5-10所示。

图5-10 运行结果

三、实验总结

1、wait()、notify()和notifyAll()这三个方法的调用者都应该是同步锁对象,如果这三个方法的调用者

不是同步锁对象,Java虚拟机就会抛出IllegalMonitorStateException异常。

2、在线程通信中的,如果需要控制多个线程按照一定的顺序轮流执行,则这几个线程的锁对象必须是同一个锁对象。

16.JAVA网络编程实验 多线程

Java网络编程实验报告 (实验六) 学号:姓名: 实验项目名称:多线程教师评分: 一、实验目的 (1)了解线程的概念。 (2)学习简单的多线程编程。 二、预习内容及要求(要求写出预习内容) 1.进程和线程的概念 进程是程序一次动态执行的过程,对应从代码加载、执行到执行结束这样一个完整的过程,也是进程自身从产生、发展到消亡的过程。 线程是比进程更小的执行单元,一个进程在执行过程中,可以产生多个线程。每个线程都有自身的产生、执行和消亡的过程。 2.线程的状态与生命周期 ●新建:当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态。此 时它已经有了相应的内存空间和其他资源。 ●运行:线程创建之后就具备了运行的条件,一旦轮到它来享用CPU资源时,即JVM将CPU 使用权切换给该线程时,此线程的就可以脱离创建它的主线程独立开始自己的生命周期了(即 run方法执行的过程)。 ●中断:有4种原因的中断,CPU资源从当前线程切换给其他线程、执行了sleep(int millsecond) 方法、执行了wait()方法、进入阻塞状态。 ●死亡:run方法结束。 3.线程的创建 在Java语言中,与线程支持密切相关的是https://www.wendangku.net/doc/773926670.html,ng.Thread类和https://www.wendangku.net/doc/773926670.html,ng.Runnable接口。Runnable 接口定义很简单,只有一个run方法。任何一个类如果希望自己的实例能够以线程的形式执行,都可以来实现Runnable接口。 继承Thread类和实现Runnable接口,都可以用来创建Thread对象,效果上并没有什么不同。继承Thread类的方法很明显的缺点就是这个类不能再继承其他的类了,而实现Runnable接口不会有这个麻烦。 另外,在继承Thread类的代码中,this其实就是指当前正在运行的线程对象,如果使用实现Runnable 接口的方式,要得到当前正在执行的线程,需要使用Thread.currentThread()方法。 线程创建后仅仅是占有了内存资源,在JVM管理的线程中还没有这个线程,此线程必须调用start ()方法(从父类继承的方法)通知JVM,这样JVM就会知道又有一个新一个线程排队等候切换了。

进程管理实验报告

进程的控制 1 .实验目的 通过进程的创建、撤消和运行加深对进程概念和进程并发执行的理解,明确进程与程序之间的区别。 【答:进程概念和程序概念最大的不同之处在于: (1)进程是动态的,而程序是静态的。 (2)进程有一定的生命期,而程序是指令的集合,本身无“运动”的含义。没有建立进程的程序不能作为1个独立单位得到操作系统的认可。 (3)1个程序可以对应多个进程,但1个进程只能对应1个程序。进程和程序的关系犹如演出和剧本的关系。 (4)进程和程序的组成不同。从静态角度看,进程由程序、数据和进程控制块(PCB)三部分组成。而程序是一组有序的指令集合。】2 .实验内容 (1) 了解系统调用fork()、execvp()和wait()的功能和实现过程。 (2) 编写一段程序,使用系统调用fork()来创建两个子进程,并由父进程重复显示字符串“parent:”和自己的标识数,而子进程则重复显示字符串“child:”和自己的标识数。 (3) 编写一段程序,使用系统调用fork()来创建一个子进程。子进程通过系统调用execvp()更换自己的执行代码,新的代码显示“new

program.”。而父进程则调用wait()等待子进程结束,并在子进程结束后显示子进程的标识符,然后正常结束。 3 .实验步骤 (1)gedit创建进程1.c (2)使用gcc 1.c -o 1编译并./1运行程序1.c #include #include #include #include void mian(){ int id; if(fork()==0) {printf(“child id is %d\n”,getpid()); } else if(fork()==0) {printf(“child2 id %d\n”,getpid()); } else {id=wait(); printf(“parent id is %d\n”,getpid()); }

实验2-2windows2000 线程同步

实验2 并发与调度 2.2 Windows 2000线程同步 (实验估计时间:120分钟) 背景知识 实验目的 工具/准备工作 实验内容与步骤 背景知识 Windows 2000提供的常用对象可分成三类:核心应用服务、线程同步和线程间通讯。其中,开发人员可以使用线程同步对象来协调线程和进程的工作,以使其共享信息并执行任务。此类对象包括互锁数据、临界段、事件、互斥体和信号等。 多线程编程中关键的一步是保护所有的共享资源,工具主要有互锁函数、临界段和互斥体等;另一个实质性部分是协调线程使其完成应用程序的任务,为此,可利用内核中的事件对象和信号。 在进程内或进程间实现线程同步的最方便的方法是使用事件对象,这一组内核对象允许一个线程对其受信状态进行直接控制 (见表4-1) 。 而互斥体则是另一个可命名且安全的内核对象,其主要目的是引导对共享资源的访问。拥有单一访问资源的线程创建互斥体,所有想要访问该资源的线程应该在实际执行操作之前获得互斥体,而在访问结束时立即释放互斥体,以允许下一个等待线程获得互斥体,然后接着进行下去。 与事件对象类似,互斥体容易创建、打开、使用并清除。利用CreateMutex() API 可创建互斥体,创建时还可以指定一个初始的拥有权标志,通过使用这个标志,只有当线程完成了资源的所有的初始化工作时,才允许创建线程释放互斥体。

为了获得互斥体,首先,想要访问调用的线程可使用OpenMutex() API来获得指向对象的句柄;然后,线程将这个句柄提供给一个等待函数。当内核将互斥体对象发送给等待线程时,就表明该线程获得了互斥体的拥有权。当线程获得拥有权时,线程控制了对共享资源的访问——必须设法尽快地放弃互斥体。放弃共享资源时需要在该对象上调用ReleaseMute() API。然后系统负责将互斥体拥有权传递给下一个等待着的线程(由到达时间决定顺序) 。 实验目的 在本实验中,通过对事件和互斥体对象的了解,来加深对Windows 2000线程同步的理解。 1) 回顾系统进程、线程的有关概念,加深对Windows 2000线程的理解。 2) 了解事件和互斥体对象。 3) 通过分析实验程序,了解管理事件对象的API。 4) 了解在进程中如何使用事件对象。 5) 了解在进程中如何使用互斥体对象。 6) 了解父进程创建子进程的程序设计方法。 工具/准备工作 在开始本实验之前,请回顾教科书的相关内容。 您需要做以下准备: 1) 一台运行Windows 2000 Professional操作系统的计算机。 2) 计算机中需安装Visual C++ 6.0专业版或企业版。 实验内容与步骤 1. 事件对象 2. 互斥体对象 1. 事件对象 清单2-1程序展示了如何在进程间使用事件。父进程启动时,利用CreateEvent() API创建一个命名的、可共享的事件和子进程,然后等待子进程向事件发出信号并终止父进程。在创建时,子进程通过OpenEvent() API打开事件对象,调用SetEvent() API使其转化为已接受信号状态。两个进程在发出信号之后几乎立即终止。 步骤1:登录进入Windows 2000 Professional。 步骤2:在“开始”菜单中单击“程序”-“Microsoft Visual Studio 6.0”–“Microsoft Visual C++ 6.0”命令,进入Visual C++窗口。

java多线程实验报告

java多线程实验报告 篇一:西北农林科技大学java多线程实验报告 实验7 多线程 1.实验目的 (1) 掌握Java多线程的概念和实现方法 (2) 掌握Java多线程的同步问题 2.实验内容 任务一:火车售票 假设有火车票1000张,创建10个线程模拟10个售票点,每个售票点100毫秒买一张票。打印出售票过程,注意使用synchronized确保同一张票只能卖出一次。程序运行结果见左图。 打开Eclipse Tickets.java public class Ticket extends Thread { int ticket =1000; String name =""; public void run(){ while(true){synchronized(name){ if(ticket "第" + Thread.currentThread().getName()+ "售票点卖出了第" + ticket-- + "张票"); } } } }} try{ } catch(InterruptedException e){ }

Thread.sleep(100); Test.java public class Test { } public static void main(String args[]){} Ticket t = new Ticket(); new Thread(t,"1").start(); new Thread(t,"2").start(); new Thread(t,"3").start(); new Thread(t,"4").start(); new Thread(t,"5").start(); new Thread(t,"6").start(); new Thread(t,"7").start(); new Thread(t,"8").start(); new Thread(t,"9").start(); new Thread(t,"10").start(); 任务二:银行存款 假设某家银行,它可接受顾客的汇款,每做一次汇款,便可计算出汇款的总额。现有两个顾客,每人都分3次,每次100元将钱到入。试编写一个程序,模拟实际作业。 程序如下: classCBank { private static int sum=0; public static void add(int n){ inttmp=sum; tmp=tmp+n;// 累加汇款总额 try{ Thread.sleep((int)(10000*Math.random())); //

进程的同步实验报告汇总

操作系统 实验报告 哈尔滨工程大学 计算机科学与技术学院

一、实验概述 1. 实验名称 进程的同步 2. 实验目的 ⑴使用EOS的信号量,编程解决生产者 消费者问题,理解进程同步的意义。 ⑵调试跟踪EOS信号量的工作过程,理解进程同步的原理。 ⑶修改EOS的信号量算法,使之支持等待超时唤醒功能(有限等待),加深理解进程同步的原理。 3. 实验类型 验证+设计 4. 实验内容 ⑴准备实验 ⑵使用EOS的信号量解决生产者-消费者问题 ⑶调试EOS信号量的工作过程 ①创建信号量 ②等待释放信号量 ③等待信号量(不阻塞) ④释放信号量(不唤醒) ⑤等待信号量(阻塞) ⑥释放信号量(唤醒) ⑷修改EOS的信号量算法 二、实验环境 WindowsXP + EOS集成实验环境 三、实验过程 1. 设计思路和流程图

图4-1.整体试验流程图

图4-2.Main 函数流程图、生产者消费、消费者流程图 2. 算法实现 3. 需要解决的问题及解答 (1). 思考在ps/semaphore.c 文件内的PsWaitForSemaphore 和PsReleaseSemaphore 函数中,为什么要使用原子操作?

答:在执行等待信号量和释放信号量的时候,是不允许cpu响应外部中断的,如果此时cpu响应了外部中断,会产生不可预料的结果,无法正常完成原子操作。 (2). 绘制ps/semaphore.c文件内PsWaitForSemaphore和PsReleaseSemaphore函数的流程图。 (3).P143生产者在生产了13号产品后本来要继续生产14号产品,可此时生产者为什么必须等待消费者消费了4号产品后,才能生产14号产品呢?生产者和消费者是怎样使用同步对象来实现该同步过程的呢? 答:这是因为临界资源的限制。临界资源就像产品仓库,只有“产品仓库”空闲生产者才能生产东西,有权向里面放东西。所以它必须等到消费者,取走产品,“产品空间”(临界资源)空闲时,才继续生产14号产品。 (4). 根据本实验3.3.2节中设置断点和调试的方法,自己设计一个类似的调试方案来验证消费者线程在消费24号产品时会被阻塞,直到生产者线程生产了24号产品后,消费者线程才被唤醒并继续执行的过程。 答:可以按照下面的步骤进行调试 (1) 删除所有的断点。 (2) 按F5启动调试。OS Lab会首先弹出一个调试异常对话框。 (3) 在调试异常对话框中选择“是”,调试会中断。 (4) 在Consumer函数中等待Full信号量的代码行(第173行)WaitForSingleObject(FullSemaphoreHandle, INFINITE); 添加一个断点。 (5) 在“断点”窗口(按Alt+F9打开)中此断点的名称上点击右键。 (6) 在弹出的快捷菜单中选择“条件”。 (7) 在“断点条件”对话框(按F1获得帮助)的表达式编辑框中,输入表达式“i == 24”。 (8) 点击“断点条件”对话框中的“确定”按钮。 (9) 按F5继续调试。只有当消费者线程尝试消费24号产品时才会在该条件断点处中断。 4. 主要数据结构、实现代码及其说明 修改PsWaitForSemaphore函数 if (Semaphore->Count>0){ Semaphore->Count--; flag=STATUS_SUCCESS; }//如果信号量大于零,说明尚有资源,可以为线程分配 else flag=PspWait(&Semaphore->WaitListHead, Milliseconds); KeEnableInterrupts(IntState); // 原子操作完成,恢复中断。 return flag; }//否则,说明资源数量不够,不能再为线程分配资源,因此要使线程等待 修改PsReleaseSemaphore函数 if (Semaphore->Count + ReleaseCount > Semaphore->MaximumCount) {

8-实验八Java多线程操作(实验报告内容)

实验八 Java多线程操作 (实验报告) 一、目的 1.掌握Java多线程操作。 二、实验内容 启动线程,线程休眠,线程同步,等待和唤醒 三、实验环境 JDK1.6+dos环境 四、实验原理 通过案例掌握多线程操作。 五、实验步骤 1、设计一个线程操作类,要求可以产生三个线程对象,并可以分 别设置三个线程的休眠时间,如下所示: 线程A,休眠10秒 线程B,休眠20秒 线程C,休眠30秒 2、生产者与消费者问题,生产者生产一台电脑,消费者马上将生 产出的电脑取走。 六、实验小结 1、class MyThread implements Runnable{

String name; int time; public MyThread(String name,int time){ https://www.wendangku.net/doc/773926670.html,=name; this.time=time; } public void run(){ try{ Thread.sleep(this.time); } catch(Exception e){ } System.out.println(https://www.wendangku.net/doc/773926670.html,+"线程,休眠"+this.time/1000+"秒"); } } public class Demo08{ public static void main(String args[]){ MyThread mt1=new MyThread("线程A",10000); MyThread mt2=new MyThread("线程B",20000); MyThread mt3=new MyThread("线程C",30000);

Java多线程实验报告

实验报告 课程名称: Java语言程序设计 姓名: 学号: 班级: 数学与计算机科学学院

数学与计算机科学学院实验报告实验名称:多线程 指导教师:日期:

if (isPrime) count++; } System.out.println(st + "~" + en + "之间共有" + count + "个质数"); } public static void main(String[] args) { UseThread thread1 = new UseThread(2, 1000); UseThread thread2 = new UseThread(1000, 2000); thread1.start(); thread2.start(); } } 第2题代码: public class Experiment14_2 { public static void main(String[] args) { MyThread t1 = new MyThread("T1"); MyThread t2 = new MyThread("T2"); t1.start(); t2.start(); System.out.println("活动线程数:" + Thread.activeCount()); System.out.println("main()运行完毕"); } } class MyThread extends Thread { public MyThread(String s) { super(s); } public void run() { for (int i = 1; i <= 3; i++) { System.out.println(getName() + "第" + i + "次运行"); try { sleep((int) (Math.random() * 100)); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(getName() + "结束"); } }

多线程同步操作多个窗口

多线程同步操作多个窗口 RunApp "notepad.exe" RunApp "notepad.exe" RunApp "notepad.exe" Delay 2000 Dimenv temp_Hwnd temp_Hwnd = 0 Dim str, arr, i str = Plugin.Window.Search("无标题- 记事本") arr = Split(str, "|") For i = 0 To UBound(arr) - 1 temp_Hwnd = Plugin.Window.FindEx(arr(i), 0, "Edit", 0) BeginThread WriteString While temp_Hwnd <> 0'判断多线程已经启动完毕,继续循环下一个。 Delay 500 Wend Next EndScript Function WriteString() Dim str, Hwnd Hwnd = temp_Hwnd temp_Hwnd = 0 Do str = WaitKey If Hwnd <> Plugin.Window.GetKeyFocusWnd Then Call Plugin.Bkgnd.KeyPress(Hwnd, str) End If Loop End Function 多线程多开窗口同步执行与子线程间的数值如何传递: 1.Dimenv IsThread, i 2.Dim arr_Thread() 3.For i = 0 To 2 4. IsThread = False'未启动线程 5. Redim Preserve arr_Thread(i) 6. arr_Thread(i) = BeginThread(EnterThread) 7. While IsThread = False'未启动成功,等待中 8. Delay 500 9. Wend 10. '跳出循环说明 IsThread = True,已经执行到了,循环继续启动下一个 11.Next

进程(线程)的同步与互斥实验报告

操作系统实验报告 课程名称操作系统实验名称进程(线程)的同步与互斥成绩 学生姓名作业君专业软件工程班级、学号 同组者姓名无实验日期2020 一、实验题目:进程(线程)的同步与互斥 二、实验目的: 自行编制模拟程序,通过形象化的状态显示,加深理解进程的概念、进程之间的状态转换及其所带来的PCB内容、组织的变化,理解进程与其PCB间的一一对应关系。1.掌握基本的同步与互斥算法,理解生产者消费者模型。 2.学习使用Windows中基本的同步对象,掌握相关API的使用方法。 3.了解Windows中多线程的并发执行机制,实现进程的同步与互斥 三、实验内容与要求: 1.实验内容 以生产者/消费者模型为依据,在Windows 环境下创建一个控制台进程,在该进程中创建n个线程模拟生产者和消费者,实现进程(线程)的同步与互斥。 2.实验要求 学习并理解生产者/消费者模型及其同步/互斥规则; 学习了解Windows同步对象及其特性; 熟悉实验环境,掌握相关API的使用方法; 设计程序,实现生产者/消费者进程(线程)的同步与互斥; 四、算法描述(含数据结构定义)或流程图 #include #include #include #include #include #include using namespace std;

#define MAX_THREAD_NUM 64 //最大线程数 #define INTE_PER_SEC 1000 //延迟时间的毫秒值 const int SIZE_OF_BUFFER = 10; //缓冲区长度 int ProductID = 0; //产品号 int ConsumeID = 0; //将被消耗的产品号 int in = 0; //产品进缓冲区时的缓冲区下标 int out = 0; //产品出缓冲区时的缓冲区下标 bool running = true; //判断程序能否继续执行的逻辑值 int g_buffer[SIZE_OF_BUFFER]; //缓冲区是个循环队列 HANDLE g_hMutex; //公有信号量,用于线程间的互斥HANDLE g_hFullSemaphore; //生产者的私有信号量,当缓冲区满时迫使生产者等待 HANDLE g_hEmptySemaphore; //消费者的私有信号量,当缓冲区空时迫使消费者等待 //定义一个结构体用于存储线程的信息 struct ThreadInfo { int serial; //线程号 char entity; //线程类别(生产者或消费者) double delay; //等待时间 double persist; //操作时间 }; //生产者 void Producer(void* p) { //定义变量用于存储当前线程的信息 DWORD m_delay; DWORD m_persist; int m_serial; //从参数中获得信息 m_serial = ((ThreadInfo*)(p))->serial; m_delay = (DWORD)(((ThreadInfo*)(p))->delay * INTE_PER_SEC); m_persist = (DWORD)(((ThreadInfo*)(p))->persist * INTE_PER_SEC); while (running) { //P操作 cout << "生产者线程 " << m_serial << " 请求生产." << endl; WaitForSingleObject(g_hEmptySemaphore, INFINITE);

线程实验报告

线 程实验报告 黄澄宇320070911241 1.分析 (1)问题阐述,描述。 运用线程的方法设计一个ftp面向客户\服务器的网络应用程序,主要包括服务器端和客户端两方面的工作。 (2)问题分析。 针对问题要求,应该能够实现客户端和服务器端的功能。其中服务器端主要对客户端进行监听。客户端向服务器端进行提出请求。 (3)寻找揭发。 TCP\IP服务器端应用程序都是通过JA V A语言中提供的SeverSocket和Socket两个有关网络的类来实现。 SeverSocket类除了建立一个Sever之外,还通过accept()方法提供了随时监听客户端连接请求的功能。 2.设计。 在服务器端指定一个用来等待连接的端口号,在客户端规定一个主机和端口号,从而在客户端和服务器端创建Socket\ServerSocket实例。

现在服务器端生成一个ServerSocket实例的对象,随时监听客户端的连接请求。 当客户端需要连接时,相应的要生成一个Socket实例的对象,并发出连接请求,其在host参数指明该主机名,port参数指明端口号。 服务器端通过accept()方法接收到客户端的请求后,开辟一个接口与之进行连接,利用输入输出流,按照一定的协议对Socket 进行读写操作。 关闭输入输出流和Socket。 3.实现。 //FTPServer.java import https://www.wendangku.net/doc/773926670.html,.*; import java.io.*; import java.util.*; public class FTPServer { public static void main(String args[]) throws Exception { ServerSocket soc=new ServerSocket(5127); System.out.println("FTP Server Started on Port Number "); while(true) {

4:一个经典的多线程同步问题汇总

一个经典的多线程同步问题 程序描述: 主线程启动10个子线程并将表示子线程序号的变量地址作为参数传递给子线程。子线程接收参数 -> sleep(50) -> 全局变量++ -> sleep(0) -> 输出参数和全局变量。 要求: 1.子线程输出的线程序号不能重复。 2.全局变量的输出必须递增。 下面画了个简单的示意图: 分析下这个问题的考察点,主要考察点有二个: 1.主线程创建子线程并传入一个指向变量地址的指针作参数,由于线程启动须要花费一定的时间,所以在子线程根据这个指针访问并保存数据前,主线程应等待子线程保存完毕后才能改动该参数并启动下一个线程。这涉及到主线程与子线程之间的同步。 2.子线程之间会互斥的改动和输出全局变量。要求全局变量的输出必须递增。这涉及到各子线程间的互斥。 下面列出这个程序的基本框架,可以在此代码基础上进行修改和验证。 //经典线程同步互斥问题 #include #include #include long g_nNum; //全局资源 unsigned int__stdcall Fun(void *pPM); //线程函数 const int THREAD_NUM = 10; //子线程个数 int main() { g_nNum = 0;

HANDLE handle[THREAD_NUM]; int i = 0; while (i < THREAD_NUM) { handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &i, 0, NULL); i++;//等子线程接收到参数时主线程可能改变了这个i的值} //保证子线程已全部运行结束 WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); return 0; } unsigned int__stdcall Fun(void *pPM) { //由于创建线程是要一定的开销的,所以新线程并不能第一时间执行到这来int nThreadNum = *(int *)pPM; //子线程获取参数 Sleep(50);//some work should to do g_nNum++; //处理全局资源 Sleep(0);//some work should to do printf("线程编号为%d 全局资源值为%d\n", nThreadNum, g_nNum); return 0; } 运行结果:

实验四 同步与互斥 Linux实验报告

实验四同步与互斥 【实验目的和要求】 1、掌握进程(线程)的同步与互斥。 2、掌握生产者消费者问题的实现方法。 3、掌握多线程编程方法。 【实验内容】 实现生产者消费者问题 1、有一个仓库,生产者负责生产产品,并放入仓库,消费者会从仓库中拿走产品(消费)。 2、仓库中每次只能入一个(生产者或消费者)。 3、仓库中可存放产品的数量最多10个,当仓库放满时,生产者不能再放入产品。 4、当仓库空时,消费者不能从中取出产品。 5、生产、消费速度不同。 【实验原理】 1、信号量mutex提供对缓冲池访问的互斥要求并初始化为1,信号量empty和 full分别用来表示空缓冲项和满缓冲项的个数,信号量empty初始化为n,信号量full初始化为0。 2、定义如下结构及数据: 定义缓冲区内的数据类型:typedef int buffer_item; 缓冲区:buffer_item buffer[BUFFER_SIZE];

对缓冲区操作的变量:int in,out; 信号量mutex提供了对缓冲池访问的互斥要求:pthread_mutex_t mutex; 信号量empty和full分别表示空缓冲顶和满缓冲顶的个数:sem_t empty,full; 可以设定生产者的生产速度及消费者的消费速度:int pro_speed,con_speed; 对缓冲区操作的自增函数:#define inc(k) if(k < BUFFER_SIZE) k = k+1;else k=0 3、并定义了如下实现问题的函数模块: 将生产的产品放入缓冲区: int insert_item(buffer_item item) 从缓冲区内移走一个产品: int remove_item(buffer_item *item) 生产者进程:void *producer(void *param) 消费者进程:void *consumer(void *param) 生产者结构进程消费者结构进程 【程序代码】 //sx.c #include

Java实验五线程

实验五线程 一实验要求 1、理解进程和线程概念; 2、掌握创建、管理和控制Java线程对象的方法; 3、了解并发执行的多线程存在的各种关系 二实验内容 1、使用线程对象或Timer定时器制作数字时钟标签组件,显示当前日期和时间,每秒刷新,将该标签添加到框架窗口。 import java.awt.FlowLayout; import java.text.SimpleDateFormat;//简单日期格式类 import java.util.Locate; import java.util.Timer;//一种工具,线程用其安排以后在后台线程中执行的任务 import java.util.TimerTask; import java.swing.JLabel; public class ShizhongJFrame extends JFrame{ { Public ShizhongJFrame(){ JFrame f=new JFrame(“数字时钟”); f.setLayout(new FlowLayout()); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setSize(200,70); final JLable lable=new JLable; final SimpleDateFormat format=new SimpleDateFormat(“H:m:s”,Locate.CHINA); f.add(lable); Timer time=new Timer(); time.scheduleAtFixedRate(new TimerTask(){ Public void run(){ Label.setText(format.format(new Date(System.currentTimeMillis()))); } },0,1000); f.setVisible(true); } Public staic void main(String arg[]){ New ShizhogJFrame(); } } 三实验内容中遇到的问题、解决方法和体会。

JAVA线程程序设计(小时钟)实验报告(附完整代码)

线程程序设计 一、课题内容和要求 内容:设计和编写一个编写一个指针式时钟程序,应用线程实现时钟的走动。 要求:本实验旨在通过实验,培养学生将JAVA 线程的相关知识点(包括线程调度,线程同步等)有机结合并加以综合应用,在实验中设计多线程程序的能力。 二、设计思路分析 class Clock:一个指针式时钟的主类 class Layout: 添加窗口和时钟组件 class ClockPaint:定义时钟组件 三、概要设计 public class Clock extends JFrame { public static void main(String[] s) ; } class Layout extends JFrame { public Layout(); } class ClockPaint extends JPanel implements Runnable { int x, y, r; int h, m, s; double rad = Math.PI / 180; public ClockPaint(int x, int y, int r); public void paint(Graphics g); public void run(); } 时钟的绘制:

运行时钟: 四、详细设计 import java.awt.*; import javax.swing.*; import java.util.*; public class Clock extends JFrame { public static void main(String[] s) { new Layout(); } } class Layout extends JFrame {// 添加窗口和时钟组件public Layout() { ClockPaint cp = new ClockPaint(20, 20, 70); add(cp);

用多线程同步方法解决生产者-消费者问题(操作系统课设)

. 题目用多线程同步方法解决生产者-消费 者问题(Producer-Consumer Problem) 学院计算机科学与技术学院 专业软件工程 班级 姓名 指导教师 年月日

目录 目录 (1) 课程设计任务书 (2) 正文 (2) 1.设计目的与要求 (2) 1.1设计目的 (2) 1.2设计要求 (2) 2.设计思想及系统平台 (2) 2.1设计思想 (2) 2.2系统平台及使用语言 (2) 3.详细算法描述 (3) 4.源程序清单 (5) 5.运行结果与运行情况 (10) 6.调试过程 (15) 7.总结 (15) 本科生课程设计成绩评定表 (16)

课程设计任务书 学生姓名:专业班级: 指导教师:工作单位:计算机科学与技术学院 题目: 用多线程同步方法解决生产者-消费者问题 (Producer-Consumer Problem) 初始条件: 1.操作系统:Linux 2.程序设计语言:C语言 3.有界缓冲区内设有20个存储单元,其初值为0。放入/取出的数据项按增序设定为1-20这20个整型数。 要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要 求) 1.技术要求: 1)为每个生产者/消费者产生一个线程,设计正确的同步算法 2)每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的当前全部内容、当前指针位置和生产者/消费者线程的自定义标识符。 3)生产者和消费者各有两个以上。 4)多个生产者或多个消费者之间须共享对缓冲区进行操作的函数代码。 2.设计说明书内容要求: 1)设计题目与要求 2)总的设计思想及系统平台、语言、工具等。 3)数据结构与模块说明(功能与流程图) 4)给出用户名、源程序名、目标程序名和源程序及其运行结果。(要注明存储各个程序及其运行结果的主机IP地址和目录。) 5)运行结果与运行情况 (提示: (1)有界缓冲区可用数组实现。 (2)编译命令可用:cc -lpthread -o 目标文件名源文件名 (3)多线程编程方法参见附件。) 3. 调试报告: 1)调试记录 2)自我评析和总结 上机时间安排: 18周一~ 五 08:0 - 12:00 指导教师签名:年月日

Windows下多线程同步机制

多线程同步机制 Critical section(临界区)用来实现“排他性占有”。适用范围是单一进程的各线程之间。它是: ·一个局部性对象,不是一个核心对象。 ·快速而有效率。 ·不能够同时有一个以上的critical section被等待。 ·无法侦测是否已被某个线程放弃。 Mutex Mutex是一个核心对象,可以在不同的线程之间实现“排他性占有”,甚至几十那些现成分属不同进程。它是: ·一个核心对象。 ·如果拥有mutex的那个线程结束,则会产生一个“abandoned”错误信息。 ·可以使用Wait…()等待一个mutex。 ·可以具名,因此可以被其他进程开启。 ·只能被拥有它的那个线程释放(released)。 Semaphore Semaphore被用来追踪有限的资源。它是: ·一个核心对象。 ·没有拥有者。 ·可以具名,因此可以被其他进程开启。 ·可以被任何一个线程释放(released)。 Ev ent Object Ev ent object通常使用于overlapped I/O,或用来设计某些自定义的同步对象。它是: ·一个核心对象。 ·完全在程序掌控之下。 ·适用于设计新的同步对象。 · “要求苏醒”的请求并不会被储存起来,可能会遗失掉。 ·可以具名,因此可以被其他进程开启。 Interlocked Variable 如果Interlocked…()函数被使用于所谓的spin-lock,那么他们只是一种同步机制。所谓spin-lock是一种busy loop,被预期在极短时间内执行,所以有最小的额外负担(overhead)。系统核心偶尔会使用他们。除此之外,interlocked variables主要用于引用技术。他们:·允许对4字节的数值有些基本的同步操作,不需动用到critical section或mutex之类。 ·在SMP(Symmetric Multi-Processors)操作系统中亦可有效运作。 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

四种进程或线程同步互斥的控制方法

四种进程或线程同步互斥的控制方法 1、临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。 2、互斥量:为协调共同对一个共享资源的单独访问而设计的。 3、信号量:为控制一个具有有限数量用户资源而设计。 4、事件:用来通知线程有一些事件已发生,从而启动后继任务的开始。 一临界区 临界区的使用在线程同步中应该算是比较简单,说它简单还是说它同后面讲到的其它方法相比更容易理解。举个简单的例子:比如说有一个全局变量(公共资源)两个线程都会对它进行写操作和读操作,如果我们在这里不加以控制,会产生意想不到的结果。假设线程A 正在把全局变量加1然后打印在屏幕上,但是这时切换到线程B,线程B又把全局变量加1然后又切换到线程A,这时候线程A打印的结果就不是程序想要的结果,也就产生了错误。解决的办法就是设置一个区域,让线程A在操纵全局变量的时候进行加锁,线程B如果想操纵这个全局变量就要等待线程A释放这个锁,这个也就是临界区的概念。 二互斥体 windows api中提供了一个互斥体,功能上要比临界区强大。也许你要问,这个东东和临界区有什么区别,为什么强大?它们有以下几点不一致: 1.critical section是局部对象,而mutex是核心对象。因此像waitforsingleobject是不可以等待临界区的。 2.critical section是快速高效的,而mutex同其相比要慢很多 3.critical section使用围是单一进程中的各个线程,而mutex由于可以有一个名字,因此它是可以应用于不同的进程,当然也可以应用于同一个进程中的不同线程。 4.critical section 无法检测到是否被某一个线程释放,而mutex在某一个线程结束之后会产生一个abandoned的信息。同时mutex只能被拥有它的线程释放。下面举两个应用mutex 的例子,一个是程序只能运行一个实例,也就是说同一个程序如果已经运行了,就不能再运行了;另一个是关于非常经典的哲学家吃饭问题的例子。 三事件 事件对象的特点是它可以应用在重叠I/O(overlapped I/0)上,比如说socket编程中有两种模型,一种是重叠I/0,一种是完成端口都是可以使用事件同步。它也是核心对象,因此可以被waitforsingleobje这些函数等待;事件可以有名字,因此可以被其他进程开启。 四信号量 semaphore的概念理解起来可能要比mutex还难,我先简单说一下创建信号量的函数,因为我在开始使用的时候没有很快弄清楚,可能现在还有理解不对的地方,如果有错误还是请大侠多多指教。 CreateSemaphore( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, // SD LONG lInitialCount, // initial count LONG lMaximumCount, // maximum count LPCTSTR lpName // object name )

实验二 编程实现进程(线程)同步和互斥

《操作系统》实验内容 实验二编程实现进程(线程)同步和互斥 1.实验的目的 (1)通过编写程序实现进程同步和互斥,使学生掌握有关进程(线程)同步与互斥的原理,以及解决进程(线程)同步和互斥的算法,从而进一步巩固进程(线程)同步和互斥等有关的内容。 (2)了解Windows2000/XP中多线程的并发执行机制,线程间的同步和互斥。 (3)学习使用Windows2000/XP中基本的同步对象,掌握相应的API函数。 (4)掌握进程和线程的概念,进程(线程)的控制原语或系统调用的使用。 (5)掌握多道程序设计的基本理论、方法和技术,培养学生多道程序设计的能力。2.实验内容 在Windows XP、Windows 2000等操作系统下,使用的VC、VB、java或C等编程语言,采用进程(线程)同步和互斥的技术编写程序实现生产者-消费者问题或哲学家进餐问题或读者-写者问题或自己设计一个简单进程(线程)同步和互斥的实际问题。 3.实验要求 (1)经调试后程序能够正常运行。 (2)采用多进程或多线程方式运行,体现了进程(线程)同步和互斥的关系。 (3)程序界面美观。 4.实验步骤 (1)需求分析:了解基本原理,确定程序的基本功能,查找相关资料,画出基本的数据流图; (2)概要设计:确定程序的总体结构、模块关系和总体流程; (3)详细设计:确定模块内部的流程和实现算法; (4)上机编码和调试; (5)运行测试; (6)编写实验报告。 5.实验报告要求 格式符合《实验报告格式》书;书写规范,排版美观,有较强的文字表达能力,能够正确地表达自己的思想,图表符合规范。 6.实验说明 本实验分两次进行,每次要求填写一份实验报告,报告中的实验名分别为:编程实现进程同步和互斥1和编程实现进程同步和互斥2,其他内容依据实验进度具体填写。

相关文档
相关文档 最新文档