java学习之多线程(1)

1.首先了解下什么是进程?

进程是指在操作系统中正在运行的一个应用程序,线程是指进程内独立执行某个任务的一个单元。

我们可以在任务管理器中打开:

 

2.什么是线程?

线程是进程中执行运算最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。

多线程:解决多任务同时执行的需求,合理使用CPU资源。多线程的运行是根据CPU切换完成,如何切换由CPU决定,因此多线程运行具有不确定性。

 

3.线程和进程的区别?

一个进程是一个独立的运行环境,它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。别把它和栈内存搞混,每个线程都拥有单独的栈内存用来存储本地数据。

一个进程中的资源是该进程中的线程所共享的,但是有个顺序,得排队,等一个线程结束之后,下一个线程才能使用。互相争抢资源得,谁先抢到CPU谁就先运行。

 

4.实例

主线程---main,默认的线程。创建了多线程,需要运行的时候通过主线程来运行。

(默认情况下是单线程。)

 

Thread 类中的 start() 和 run() 方法有什么区别?

调用 start() 方法才会启动新线程;如果直接调用 Thread 的 run() 方法,它的行为就会和普通的方法一样;为了在新的线程中执行我们的代码,必须使用 Thread.start() 方法。

线程的run()方法是由java虚拟机直接调用的,如果我们没有启动线程(没有调用线程的start()方法)而是在应用代码中直接调用run()方法,那么这个线程的run()方法其实运行在当前线程(即run()方法的调用方所在的线程)之中,而不是运行在其自身的线程中,从而违背了创建线程的初衷;

 

创建多线程的方式:

(1)内部类分别继承Thread方法

(2)类实现Runnable接口

 

方法一:

(1)创建内部类,几个线程几个内部类

(2)线程的执行内容写在该内部类的run()方法中,类似于是线程的main方法

【下面有作业一、二用方法一实现】

 

方法二:

类实现Runnable抽象类,并实现run方法,将内容写在run方法中,在main中启动即可

方法二的弊端:不同线程之间只能做一个动作(因为只有一个run()方法)

方法二实例:

package aEightThirty;

public class OneTwoThree implements Runnable{

	public void run() {
		int i=0;
		while(i<5){
			System.out.println(Thread.currentThread().getName()+"---"+i);//获取当前线程的名字
			i++;
		}
		
	}
	public static void main(String [] args){
		OneTwoThree twt = new OneTwoThree();
		Thread t1 = new Thread(twt);
		Thread t2 = new Thread(twt);
		Thread t3 = new Thread(twt);
		t1.setName("one");//为线程对象设置名字
		t2.setName("two");
		t3.setName("three");
		
		t1.setPriority(8);//为对象设置优先级
		t2.setPriority(5);
		t3.setPriority(2);
		
		t1.start();
		t2.start();
		t3.start();
	}

}

设置优先级,0-10,优先级高的先执行

但执行效果如下,理由是现在电脑配置好,多核cpu,所以,要想实现效果,令只有一个cpu作用即可

任务管理器 ---> 详情信息 ---> eclipse ---> 右键 ---> 设置相关性 ---> 设置只有cpu0作用

 

作业一

记录做饼和吃饼的过程

1.tom每3秒做一张饼
2.jerry每5秒吃一张饼
3.一共做10饼
4.求tom做完的时间
5.求jerry吃完的时间

编写程序反应过程

package aEightThirty;

public class TomAndJerry {
	int tomCount = 0;			//记录tom做饼的个数
	int jerryCount = 0;			//记录jerry吃饼的个数

	long tomTime = 0;			//记录tom的时间差
	long jerryTime = 0;			//记录jerry的时间差

	class Tom extends Thread {	//tom的线程
		public void run() {
			long tomStart = System.currentTimeMillis();		//做饼之前获取当前系统时间

			while (tomCount < 10) {							
				try {
					sleep(3000);							//睡3秒再执行
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				tomCount++;
				System.out.println("tom在做第" + tomCount + "张饼");
			}
			tomTime = System.currentTimeMillis() - tomStart;	//用执行十次后的当前时间 - 开始的时间 = 做饼时间差

			System.out.println("tom做完的时间: " + tomTime);
		}

	}

	class Jerry extends Thread {  //jerry的线程
		public void run() {
			long jerryStart = System.currentTimeMillis();
			while (jerryCount < 10) {
				try {
					sleep(5000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				jerryCount++;
				System.out.println("jerry在吃第" + jerryCount + "张饼");
			}
			jerryTime = System.currentTimeMillis() - jerryStart;

			System.out.println("jerry吃完的时间: " + jerryTime);
		}
	}

	public void execute() {
		Tom t = new Tom();
		Jerry j = new Jerry();

		t.start();
		j.start();

	}

	public static void main(String[] args) {
		TomAndJerry tj = new TomAndJerry();
		tj.execute();
	}

}

实现结果:

【注:设置当前时间那个只能用System.currentTimeMillis()而不能Thread.getTime(),第二个相减是零】

join函数
 //join礼让执行,对象.join()就是让别人礼让我这个对象
        tom.start();
        try {
            tom.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        jerry.start();

执行效果就是tom十张饼都做完了,jerry 才开始吃

 

 

作业二 (出租车 和公交车  同时接人)(思考题)
编写程序反应 车站的运行状况
1.站内原有乘客 78人
2.出租车每4秒进站一次 接走乘客4人
3.公交车每16秒进站一次 接走乘客16人
4.每2秒又有一名新的乘客进站


当站内乘客第一次为0的时候
用了几辆出租车
用了几辆公交车
接走的客流量共多少人
时间是多少

package aEightThirty;

public class TaxiAndBus {
	int count = 78;					//存着站内的人数
	int taxiCount = 0;				//用了几辆出租车
	int busCount = 0;				//用了几辆公交车
	int sum=0;						//接走的客流量共多少人
	long startTime = System.currentTimeMillis();//存放程序开始的时间
	
	class Taxi extends Thread{
		public void run(){
			while(count!=0){		//车一次接走4个
				

				try {
					sleep(4000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}zero();
				//因为存在出租车载少于4大于0的情况
				int num = (count-4)>0?4:count;	//单次载的人数
				count = (count-4)>0?count-=4:0;	
				taxiCount++;
				sum+=num;
				System.out.println("出租车接走乘客"+num+"人,剩余乘客"+count+"名");
			}
		}
	}
	class Bus extends Thread{
		public void run(){
			while(count!=0){		//车一次接走4个
				

				try {
					sleep(16000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}zero();
				int num = (count-16)>0?16:count;
				count = (count-16)>0?count-=16:0;
				busCount++;
				sum+=num;
				System.out.println("公交车接走乘客"+num+"人,剩余乘客"+count+"名");
				
			}
		}
	}
	class Passage extends Thread{
		public void run(){
			while(count!=0){		//车一次接走4个
				

				try {
					sleep(2000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				zero();
				count+=1;
				System.out.println("一名新的乘客进站,剩余乘客"+count+"名");

				
			}
		}
	}
	public void execute(){
		Taxi t = new Taxi();
		Bus b = new Bus();
		Passage p = new Passage();
		
		t.start();
		b.start();
		p.start();
	}
	
	public void zero(){	//当站内人数为零时候
		if(count == 0){
			System.out.println("当站内乘客第一次为0的时候:");
			System.out.println("用了"+taxiCount+"辆出租车");
			System.out.println("用了"+busCount+"辆公交车");
			System.out.println("接走的客流量共"+sum+"人");
			System.out.println("时间是"+(System.currentTimeMillis() - startTime));
			System.exit(0);
		}
	
	}
	public static void main(String [] args){
		TaxiAndBus tb = new TaxiAndBus();
		tb.execute();
	}
}

运行结果:

程序中存在同步的问题,所以同上,设置只有cpu0可以使用

也可以用sychronize来加锁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

书文的学习记录本

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值