实验名称 实验六、多线程 日期 2020年 07 月02 日
一、实验目的:
1、掌握线程的创建。
2、掌握线程的调度。
3、掌握线程的同步。
4、了解线程池的使用。
二、实验环境:
PC+Windows10+Eclipse
三、实验内容:
(写出主要的内容)
1、设有一个银行账户,里面有2000元钱。该账户归tom和jack两个人共同所有。每个人每 次可以取100元钱。编写一个类BankAccount表示银行账户,void withdraw(int count)方法表 示取钱,int getbalance()方法用来获取银行账户余额。创建两个线程分别表示tom和jack两 个人。要求输出取钱的过程,以及每次取钱后的账户余额。 为了更好的模拟多线程的交错运行效果,可以每次取钱之前让线程暂停20毫秒。运行结果如下图。
代码:
package 实验六;
public class Count implements Runnable{
int money=2000;
int Getmoney() {
money=money-100;
return money;
}
public void run() {
while(this.money>100) {
synchronized(this) {
try {
Thread.sleep(20);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+" withdraw 100 balance left "+Getmoney());
}
}
public static void main(String[] args) {
Count a=new Count();
Thread t1=new Thread(a);
t1.setName("Tom");
Thread t2=new Thread(a);
t2.setName("Jack");
t1.start();
t2.start();
}
}
2、计算0~999的和,要求使用多线程的方法,第一个线程计算前500个数的和,第二个线 程计算后500个数的和。然后将两个计算结果相加。第一个线程名为thread1,第二个线程名 为thread2。注意:在计算最终结果之前,必须确保两个线程都已经计算完成。程序运行结果如下:
代码:
package 实验六;
public class ThreadAdd {
public static void main(String[] args) {
int sum;
Thread1 t1s=new Thread1();
Thread2 t2s=new Thread2();
Thread t1=new Thread(t1s);
Thread t2=new Thread(t2s);
t1.setName("thread1");
t2.setName("thread2");
t1.start();
try {
t1.join();
}catch(InterruptedException e) {
e.printStackTrace();
}
t2.start();
try {
t2.join();
}catch(InterruptedException e) {
e.printStackTrace();
}
sum=t1s.get()+t2s.get();
System.out.println("最终结果为:"+sum);
}
}
class Thread1 implements Runnable{
private int sum1=0;
public void run() {
for(int i=0;i<500;i++) {
sum1+=i;
}
System.out.println("thread1计算完成 结果为:"+sum1);
}
public int get() {
return sum1;
}
}
class Thread2 implements Runnable{
private int sum2=0;
public void run() {
for(int i=500;i<1000;i++) {
sum2+=i;
}
System.out.println("thread2计算完成 结果为:"+sum2);
}
public int get() {
return sum2;
}
}
3、编程模拟售票系统,模拟多个窗口(至少4个)同时出售100张车票的情况;用实现Runnable接口的方法实现多线程。程序运行结果如下:
代码:
public class Soldticket
{
public static void main(String[] args) {
TicketSell t1 = new TicketSell();
TicketSell t2 = new TicketSell();
TicketSell t3 = new TicketSell();
TicketSell t4 = new TicketSell();
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t4.setName("窗口4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class TicketSell extends Thread{
private static int ticket = 100;
@Override
public void run() {
while(true){
synchronized (TicketSell.class) {
if(ticket>=0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.getName()+" "+"剩余 "+ticket+" 张票!");
ticket--;
}else{
break;
}
}
}
}
}
4、使用多线程同步和互斥方式解决5个哲学家问题。
代码:
public class Eating
{
public boolean[] isUsing=new boolean[5];
public synchronized void takeChopsticks(int index){
while(isUsing[index]||isUsing[(index+1)%5]){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
isUsing[index]=true;
isUsing[(index+1)%5]=true;
System.out.println("哲学家"+index+"拿起筷子");
}
public synchronized void putChopsticks(int index){
isUsing[index]=false;
isUsing[(index+1)%5]=false;
System.out.println("哲学家"+index+"放下筷子");
notify();
}
}
class Philosopher implements Runnable{
private int index;
public static Eating chop=new Eating();
public Philosopher(int index) {
this.index = index;
}
public synchronized void thinking(){
System.out.println("哲学家"+Thread.currentThread().getName()+"在思考");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public synchronized void eating(){
System.out.println("哲学家"+index+"在吃饭");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
thinking();
chop.takeChopsticks(index);
eating();
chop.putChopsticks(index);
}
}
}
public class Philosopher
{
public class Philosopher implements Runnable{
private int index;
public Eating chop=new Eating();
public Philosopher(int index) {
this.index = index;
}
public synchronized void thinking(){
System.out.println("哲学家"+Thread.currentThread().getName()+"在思考");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public synchronized void eating(){
System.out.println("哲学家"+index+"在吃饭");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run() {
while(true){
thinking();
chop.takeChopsticks(index);
eating();
chop.putChopsticks(index);
}
}
}
}
public class test
{
public static void main(String[] args) {
Philosopher p1=new Philosopher(0);
Philosopher p2=new Philosopher(1);
Philosopher p3=new Philosopher(2);
Philosopher p4=new Philosopher(3);
Philosopher p5=new Philosopher(4);
new Thread(p1,"0").start();
new Thread(p2,"1").start();
new Thread(p3,"2").start();
new Thread(p4,"3").start();
new Thread(p5,"4").start();
}
}
四、心得体会:
通过此次实验,知道了线程也称为轻型进城,是处理器调度的基本单位,灵活使用多线程进行程序设计,可以有效地简化设计任务,提高程序执行效率;掌握了线程的创建;掌握了线程的调度;掌握了线程的同步;了解了线程池的使用。创建进程时,run()方法必须重写,虽然run()方法事线程体,但不能直接调用run()方法,而是通过调用start()方法来启动线程。