【黑马程序员】Java基础05:多线程与其安全问题

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------


一、进程与线程

进程是一个正在执行中的程序。每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元。

线程就是进程中的一个独立的控制单元,线程在控制着进程的执行,一个进程中至少有一个线程。

JVM启动时会有java.exe进程,该进程中至少有一个线程负责java程序的执行,而且这个线程运行的代码存在于main方法中,即为主线程;更确切的说,java虚拟机启动时,不止一个线程,还有负责垃圾回收机制的线程也会启动。

 

二、创建线程

两种传统方式:

1、在Thread中覆盖run()方法,并编写运行代码;

	Thread thread = new Thread(){
		public void run() {
			while(true){
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("1:"+Thread.currentThread().getName());
				//System.out.println("2:"+this.getName());//当前线程可以用this表示
			}
		}
	};
	thread.start();

2、在传递给Thread对象的Runnable对象的run()方法中编写运行代码。

	Thread thread2 = new Thread(new Runnable() {
		
		public void run() {
			while(true){
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("1:"+Thread.currentThread().getName());
			}
			
		}
	});
	thread2.start();

这二种方法的区别:

1、实现Runnable接口创建线程更加体现了面向对象的思维,而且避免了单继承的局限性;

2、继承Thread:线程代码放在子类Threadrun方法中;实现Runnable:线程代码放在接口子类的run方法中。

 

注意:

1、如果多线程中用到异常语句,只能try,不能在run()方法抛出异常;

2、多线程并不会提高程序的运行效率,CPU来回切换,反而会降低效率;而多线程下载是因为要去抢占服务器端的资源,每个线程的速率其实没有变化;

3、如果在Thread子类覆盖的run方法中编写了运行代码,也为Thread子类对象传递了一个Runnable对象,那么线程运行时会执行子类的run方法;

	//Thread子类覆盖了run方法,也传递了Runnable对象,运行结果为:Thread:Thread-0,即运行的是子类的run方法。
	Thread thread3 = new Thread(new Runnable(){

		public void run() {
			while(true){
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("Runnable:"+Thread.currentThread().getName());
			}
		}
	}){
		public void run() {
			while(true){
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("Thread:"+Thread.currentThread().getName());
			}
		}
	};
	thread3.start();

三、多线程的安全问题

多线程的安全问题:当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,CPU进行切换,另一个线程参与进来执行,就会导致共享数据的错误。

安全问题出现的原因:多个线程访问出现延迟线程的随机性 。

 

解决办法:

1同步代码块对多条线程操作共享数据的语句,只能让一个线程执行完,再让其它线程继续执行,代码格式:

synchronized(对象){

需要同步的代码;

}

2同步函数:在函数上加上synchronized修饰符即可。例:publicsynchronized void test(){}

 

同步的前提:

1、必须要有两个或者两个以上的线程

2、必须是多个线程使用同一个锁

3、必须保证同步中只能有一个线程在运行。

 

同步的好处:解决了多线程的安全问题。

同步的弊端:多线程都会去判断同步锁,较为消耗资源。

 

同步函数的锁:

1、同步函数需要被对象调用,那么函数都有一个所属对象引用:就是this,所以同步函数使用的锁是this。

2、当同步函数被静态修饰后,静态成员初始化时,内存中还没有本类对象,但是一定有类对应的字节码文件对象类名.class该对象的类型是Class类。所以,静态的同步函数,使用的是该函数所在类的字节码文件对象。

 

四、线程间通信

线程间通信其实就是多个线程在操作同一个资源,但是操作的动作不同。

等待唤醒机制:

在操作同步中的线程时,必须标识所操作线程持有的锁只有同一个锁上的被等待线程才可以被同一个锁上的notify()方法唤醒不可以对不同锁中的线程进行唤醒。也就是说,等待和唤醒必须是同一个锁。

 

停止线程:

1让run()方法结束运行:开启多线程运行,通常是循环结构,只要控制了循环,就可以让run方法结束;

2定义循环结束标记使用Thread类的interrupt(中断)方法该方法是结束线程的冻结状态,使线程回到运行状态中来。

package blog.itheima;

/*线程程间通信,同步示例代码:
 
需求:
有二个线程,子线程先执行10次,然后主线程执行100次,如此交替运行,一共执行50次为止。*/

public class TraditionalThreadCommunication {

	public static void main(String[] args) {
		
		final Business business = new Business();
		new Thread(new Runnable() {
			//子线程总共执行50次
			public void run() {
				for(int i=1; i<=50; i++){
					/*创建一个对象,把这一段代码当作方法放在对象之中
 					synchronized (TraditionalThreadCommunication.class) {
						for(int j=1; j<=10; j++){
							System.out.println(Thread.currentThread().getName()+"...执行次数:"+j+"...第"+i+"次循环");	
						}
					}*/
					business.sub(i);
				}
			}
		}).start();
		
		//主线程总共执行50次
		for(int i=1; i<=50; i++){
			/*synchronized (TraditionalThreadCommunication.class) {
				for(int j=1; j<=10; j++){
					System.out.println(Thread.currentThread().getName()+"...执行次数:"+j+"...第"+i+"次循环");	
				}
			}*/
			business.main(i);
		}
	}
}

class Business{
	private boolean flag = false;
	public synchronized void sub(int i){
		while(flag){
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		//初始为false,子线程先执行10次
		for(int j=1; j<=10; j++){
			System.out.println(Thread.currentThread().getName()+"...执行次数:"+j+"...第"+i+"次循环");	
		}
		//子线程执行10次之后,更改标记进入等待,唤醒主线程
		flag = true;
		this.notify();
	}
	
	public synchronized void main(int i){
		//if(!flag){
		//初始为false,子线程先执行,主线程等待
		while(!flag){//用while会二次判断条件,比if判断一次更健壮
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		//子线程执行10次之后,更改标记为true,主线程执行100次
		for(int j=1; j<=100; j++){
			System.out.println(Thread.currentThread().getName()+"...执行次数:"+j+"...第"+i+"次循环");	
		}
		//主线程执行100次之后,更改标记进入等待状态,唤醒子线程
		flag = false;
		this.notify();
	}
}


---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值