本站已关停,现有内容仅作科研等非赢利用途使用。特此声明。
查看: 988|回复: 2
打印 上一主题 下一主题

Android菜鸟饭团#Java中文学习#第二十一课 活动笔记

[复制链接]
跳转到指定楼层
1#
发表于 2015-5-13 23:20:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 houzhao 于 2015-5-15 12:28 编辑

Android菜鸟饭团#Java中文学习#第二十一课 活动笔记

1.什么是线程同步?
当使用多个线程来访问同一个数据时,非常容易出现线程安全问题(比如多个线程都在操作同一数据导致数据不一致),所以我们用同步机制来解决这些问题。

2.为什么要使用线程同步?
线程的同步是为了防止多个线程访问同一个数据对象时,对数据造成的破坏。
java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查),将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程的调用,从而保证了该变量的唯一性和准确性。

怎么样实现线程同步?
使用关键字synchronized 锁定对象(执行当前线程语句中不会被打断)。
使用方法
1)
2)放在方法声明中,表示整个方法为同步方法。
【补充】
synchronized的用法
1、方法声明时使用,放在范围操作符(public等)之后,返回类型声明(void等)之前.这        时,线程获得的是成员锁,即一次只能有一个线程进入该方法,其他线程要想在此时调用

该方法,只能排队等候,当前线程(就是在synchronized方法内部的线程)执行完该方法后,别的线程才能进入.

2、.对某一代码块使用,synchronized后跟括号,括号里是变量,这样,一次只有一个线程进入该代码块.此时,线程获得的是成员锁.

3、synchronized后面括号里是一对象,此时,线程获得的是对象锁.

4、如果线程进入,则得到当前对象锁,那么别的线程在该类所有对象上的任何操作都不能进行.在对象级使用锁通常是一种比较粗糙的方法。为什么要将整个对象都上锁,而不允许其他线程短暂地使用对象中其他同步方法来访问共享资源?如果一个对象拥有多个资源,就不需要只为了让一个线程使用其中一部分资源,就将所有线程都锁在外面。由于每个对象都有锁,可以如下所示使用虚拟对象来上锁:

5、synchronized后面括号里是类,此时,线程获得的是对象锁

6、如果线程进入,则线程在该类中所有操作不能进行,包括静态变量和静态方法,实际上,对于含有静态方法和静态变量的代码块的同步,我们通常用5来加锁。
【注意】

何时需要同步?
在多个线程同时访问互斥(可交换)数据时,应该同步以保护数据,确保两个线程不会同时修改更改它。

对于非静态字段中可更改的数据,通常使用非静态方法访问。
对于静态字段中可更改的数据,通常使用静态方法访问

5.其中可能会发成的问题是什么?
线程死锁(当两个线程被阻塞,每个线程在等待另一个线程时就发生死锁。)
死锁发生在当两个线程对一对同步对象有循环依赖关系时。

通俗的讲:
既然可以上锁,那么假如有2个线程,一个线程想先锁对象1,再锁对象2,恰好另外有一个线程先锁对象2,再锁对象1。
在这个过程中,当线程1把对象1锁好以后,就想去锁对象2,但是不巧,线程2已经把对象2锁上了,也正在尝试去锁对象1。
什么时候结束呢,只有线程1把2个对象都锁上并把方法执行完,并且线程2把2个对象也都锁上并且把方法执行完毕,那么就结束了,但是,谁都不肯放掉已经锁上的对象,所以就没有结果,这种情况就叫做线程死锁。

其中一个解决方法就是加大锁定的粒度,也就是尽量锁大的对象,不要锁得太小,还有尽量不要同时锁2个或2个以上的对象,但是还有待于进一步研究。

额外的收获
notify方法(唤醒正在wait中的线程继续进行)。
wait方法是object类中的(令当前对象正在访问或锁定的线程暂停)
会抛出InterruptedException异常。
Notify也是Object类中的方法,用于唤醒在此对象上等待着的某一个线程,如果有很多线程挂起的话,就随机地决定哪一个。注意,是随机的,这时可以用notifyAll来唤醒所有的。一定要注意这个问题,除非你明确地知道你在做什么,否则最好就是用notifyAll。

Waite和sleep区别
对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。
Sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
在调用sleep()方法的过程中,线程不会释放对象锁。
而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对fy()方法后本线程才进入对象锁定池准备,获取对象锁进入运行状态。

【注意】
wait()和notify()必须包括在synchronized代码块中,等待中的线程必须由notify()方法显式地唤醒,否则它会永远地等待下去。很多人初级接触多线程时,会习惯把wait()和notify()放在run()方法里,一定要谨记,这两个方法属于某个对象,应在对象所在的类方法中定义它,然后run中去调用它。

【书记员:候钊】
每一个技术小白都有一个成为大神的梦想,现在Android菜鸟饭团就给你这个成就梦想的机会。我们提供最新的Android技术教学,只要你又耐心和毅力就一定会在这里有所收获。
Android菜鸟饭团南阳GDG组织发起,秉承着开放、分享、创新的原则,希望通过GDG社区的力量能够给更多的想要学习Android开发技术的小白们创造一个学习,交流,分享的环境。同往常的GDG活动一样,我们依然是任性的一个子都不要,并且还在周六的分享中提供盒饭和不定期的惊喜小礼物呦~所以快来加入我们吧,为你的大神梦想迈出第一步。
把你的个人信息和申请理由快快发送到android@chuang1.net,前来加入我们吧
ChinaGDG.com
回复

使用道具 举报

2#
发表于 2015-5-14 07:15:46 | 只看该作者
一个线程的创建到底有哪些需要方法运行?
ChinaGDG.com
回复 支持 反对

使用道具 举报

3#
发表于 2015-5-15 18:38:41 | 只看该作者
wangliyang 发表于 2015-5-14 07:15
一个线程的创建到底有哪些需要方法运行?


我在网上查找资料的时候,看到了这样的解释,看看是不是你想要的答案:

继承Thread类创建线程类(Thread类已经实现了Runnable接口)

1、Thread类的构造方法有8个,但常用的只有4个,分别为:

Thread类中的两个最主要的方法:
(1)run()—包含线程运行时所执行的代码,即线程需要完成的任务,是线程执行体。
(2)start()—用于启动线程。

2、通过继承Thread类来创建并启动多线程的步骤:
(1)定义Thread类的子类,并覆盖该类的run()方法。
(2)创建Thread子类的实例,即创建线程对象。
(3)用线程对象的start()方法来启动该线程。
ChinaGDG.com
回复 支持 反对

使用道具 举报

*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表