黑马程序员——多线程知识总结1

------- android培训java培训、期待与您交流! ----------

多线程算是Java中比较重要的一个部分了,下面把个人觉得的一些重要内容和大家分享下~~

概述

进程:正在执行中的程序
线程:进程中一个负责程序执行的控制单元(执行路径)。
P.S.
1、一个进程中可以有多个执行路径,称之为多线程。
2、一个进程中至少要有一个线程。

多线程的好处:解决了多部分代码同时运行的问题。
多线程的弊端:线程太多,会导致效率的降低。

其实,多个应用程序同时执行都是CPU在做着快速的切换完成的。这个切换是随机的。CPU的切换是需要花
费时间的,从而导致了效率的降低。————>多线程的实质(⊙o⊙)哦。

在单线程程序中,只有上一句代码执行完,下一句代码才有执行的机会。


如何定义一个线程?

创建线程方式一:继承Thread类
1.定义一个类继承Thread类。
2.覆盖Thread类中的run方法。
3.直接创建Thread的子类对象创建线程。
4.调用start方法开启线程并调用线程的任务run方法执行。

run方法中定义的就是线程要运行的任务代码。

P.S. 

继承Thread类的类对象调用start方法开启了线程,并执行线程的run方法;

而直接调用run方法,仅仅是对象调用方法,没有新线程开启;


创建线程方式二:实现Runnable接口
1.定义类实现Runnable接口。
2.覆盖接口中的run方法,将线程的任务代码封装到run方法中。
3.通过Thread类创建线程对象,并将Runnable接口的子类对象作为Thread类的构造函数的参数进行传递。
4.调用线程对象的start方法开启线程。

方式二更为常用~~(Java中是单继承,使用方式二避免了Java单继承的局限性。)

其实下面才是重点——多线程的安全性

问题的原因:
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,
另一个线程参与进来执行。导致共享数据的错乱。


解决办法:
对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。

在java中,用同步代码块就可以解决这个问题。
同步代码块的格式:
synchronized(对象){
需要被同步的代码;其实就是操作共享数据的语句
}

对象如同锁。持有锁的线程可以在同步中执行。没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。
同步的好处:解决了线程的安全问题。
同步的弊端:当线程相当多时,因为每个线程都会去判断同步上的锁,无形中会降低程序的运行效率。
同步的前提:必须有多个线程并使用同一个锁。

当synchronized出现在函数声明上,函数就具备了同步性(同步函数)

利用同步代码块解决安全问题案例:

/*
需求:
银行有一个金库。
有两个储户分别存300元,每次存100,存3次。

如何找问题:
1,明确哪些代码是多线程运行代码。
2,明确共享数据。
3,明确多线程运行代码中哪些语句是操作共享数据的。

*/


class Bank
{
	private int sum;//金库金额
	public void add(int n)
	{
		synchronized(this)
		{
			sum = sum + n;
			System.out.println("sum="+sum);
		}
	}
}

class ChuHu implements Runnable
{
	private Bank b = new Bank();
	public void run()//储户向金库存钱

	{		
		for(int x=0; x<3; x++)
		{
			b.add(100);
		}
	}
}


class  BankDemo
{
	public static void main(String[] args) 
	{
		ChuHu c = new ChuHu();
		Thread t1 = new Thread(c);
		Thread t2 = new Thread(c);
		t1.start();
		t2.start();
	}
}


同步函数和同步代码块的区别:
1.同步函数的锁是固定的this。
2.同步代码块的锁是任意的对象。

静态的同步函数使用的锁是该函数所属字节码文件对象,可以用当前类名.class表示。

总结完各种同步后,提醒各位小心死锁(同步中嵌套同步,但个同步中锁不一样)

上个死锁的例子,小心避免啊

class Test implements Runnable
{
	private boolean flag;//标记位,好让下面出现死锁
	Test(boolean flag)
	{
		this.flag = flag;//两线程创建时传入不同标记
	}

	public void run()
	{
		if(flag)//标记位true的到这来
		{
			while(true)
			{
				synchronized(MyLock.locka)//持有locka
				{
					System.out.println(Thread.currentThread().getName()+"...if locka ");
					synchronized(MyLock.lockb)//标记位false的线程持有lockb时,这里就停住进不去了
					{
						System.out.println(Thread.currentThread().getName()+"..if lockb");					
					}
				}
			}
		}
		else//标记位false的
		{
			while(true)
			{
				synchronized(MyLock.lockb)//持有lockb
				{
					System.out.println(Thread.currentThread().getName()+"..else lockb");
					synchronized(MyLock.locka)//当上面的持有locka这里就停这了
					{
						System.out.println(Thread.currentThread().getName()+".....else locka");
					}
				}
			}
		}
	}
}

//封装两个锁方便使用
class MyLock
{
	static Object locka = new Object();
	static Object lockb = new Object();
}

class  DeadLockTest
{
	public static void main(String[] args) 
	{
		Thread t1 = new Thread(new Test(true));
		Thread t2 = new Thread(new Test(false));
		t1.start();
		t2.start();
	}
}

额,先到这里,下回在更


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值