您的位置:首页 > 职场人生

黑马程序员_JAVA基础4_线程,同步,单例

2014-09-09 15:55 253 查看
------- android培训java培训、期待与您交流! ----------

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

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

创建线程的第一种方式: 继承Thread类,继承类Thread,复写run方法,将自定义代码存储在run方法中,让线程运行,创建对象,调用线程的start方法。

第二种创建线程的方法步骤:

1.定义类实现Runable接口
2.覆盖Runable接口中的run方法
3.通过Thread类建立线程对象
4.将runnable接口的子类对象作为实际参数传递给Thread类的构造函数,自定义的run方法所属的对象是runnable接口的子类对象,所以要让线程
去指定指定对象的run方法,就必须明确该run方法所属对象。
5.调用Thread类的start方法开启线程并调用runnable接口子类的run方法。

发现运行结果每一次不同:因为多个线程都获取cpu的执行权,CPU执行到谁,就运行谁。

为什么要覆盖run方法:Thread类用于描述线程,该类就定义了一个功能,用于运行线程要运行的代码,该存储功能就是run方法,也就是run方法中,用于存储线程要运行的代码。

static  Thread currentThread();获取当前线程对象
get name() 获取线程名称

实现方式和继承方式的区别:实现方式避免了单继承的局限性。在定义线程时,建议使用实现方式。

多线程安全问题
          当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完;
          另一个线程参与进来执行,导致共享数据的错误。
解决办法:
          对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不得参与执行。

 synchronized(){}同步代码块

同步函数,synchronized作为修饰符,对象如有锁,持有锁的线程可以在同步中运行。

同步的前提:
1.必须要有两个或两个以上的线程;
2.必须是多个线程使用同一个锁。

必须保证同步中只能有一个线程在运行
好处:解决了多线程的安全问题
弊端:多个线程都需要判断锁,消耗资源

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

同步函数 使用的锁是this。线程间通讯:其实就是多个线程在操作同一个资源,但操作的动作不同。wait();notify();notifyAll()都是用在同步中,因为要对持有监视器(锁)的线程操作,所以要使用在同步中,因为只有同步才有锁。

为什么这些操作线程的方法要定义在object类中?
因为这些方法在操作同步中的线程时都必须要标示他们所操作线程只有的锁,只有同一个锁上的被等待线程,才可以被同一个锁上的notify唤醒。不可以对不同锁中的线程进行唤醒。

等待和唤醒必须是同一个锁,而锁可以是任意对象,所以可以被任意对象调用的方法定义在object类中

jdk1.5中提供了多线程升级解决方案,将同步Synchronized替换成现实Lock操作。将object中的wait,notify,notifyAll,替换成condition对象,该对象可以Lock锁进行获取,实现了本方只唤醒对方的操作。

生产-消费模型
class Producer implements Runnable{
private Source s;
Producer(Source s){
this.s = s;
}
public void run(){
while(true){
s.set();
}
}
}
class Consumer implements Runna
4000
ble{
private Source s;
Consumer(Source s){
this.s = s;
}
public void run(){
while(true){
s.out();
}
}
}
class Source{

String str = "商品";
private boolean flag = true;

private Lock lock = new ReentrantLock();//lock是接口,ReentrantLock是类
private Condition condition_pro = lock.newCondition();
private Condition condition_con = lock.newCondition();

public void set(){
try{
lock.lock();
if(!flag)
condition_pro.await();
System.out.println(Thread.currentThread()+"生产-----"+str);
flag = false;
condition_con.signal();
}
catch(Exception e){
}
finally{
lock.unlock();
}
}

public void out(){
try{
lock.lock();
if(flag)
condition_con.await();
System.out.println(Thread.currentThread()+"消费--"+str);
flag = true;
condition_pro.signal();
}
catch(Exception e){

}
finally{
lock.unlock();
}
}

}
class CDemo{
public static void main(String[] args){
Source s = new Source();
new Thread(new Producer(s)).start();
new Thread(new Consumer(s)).start();
}
}


如何停止线程?
只有一种方法让run方法结束:开启多线程运行,运行代码通常是循环结构,只要控制住循环,就可以让run方法结束,也就是让线程结束。 
特殊情况:
当线程处于冻结状态,就不会读取到标记,那么线程就不会结束。当没有指定的方式让线程恢复到运行状态中,这时,需要对冻结状态进行清除,强制让线程恢复到运行状态中来,这样就可以操作标记让线程结束。

Thread类提供该方法interrupt();
守护线程:当正在运行的线程全为守护线程时,Java虚拟机退出
setDeamon(boolean);
join:可以用来临时加入线程执行
yield()释放执行权

java中23种设计模式:
单例设计模式:解决一个类在内存中只存在一个对象

想要保证对象唯一
1.为了避免其他程序过多建立该类对象,先控制禁止其他程序建立该类对象;
2.还为了让其他程序可以访问该类对象,只好在本类中,自定义一个对象;
3.为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。

如何用代码体现?
1.将构造函数私有化;
2.在类中创造一个本类对象;
3.提供一个方法可以获取到该对象。

对于事物,该怎么描述还怎么描述,当需要将该事物的对象在内存中保证唯一时,就将以上三步加上即可。

单例设计模式一
饿汉式
class  Single
{
private static Single s = new Single();
private Single(){}
public static Single getInstance()
{
return s;
}
}
单例设计模式二
懒汉式/延迟加载

多线程时存在安全隐患
class  Single
{
private static Single s = null;
private Single(){}
public static Single getInstance()
{
if(s==null)
s = new Single();
return s;
}
}
定义单例,建议使用饿汉式
面试多考懒汉式
class  Single
{
private static Single s = null;
private Single(){}
public static synchronized Single getInstance()
{
if(s==null)
s = new Single();
return s;
}
}

以上每次都要判断锁,低效,所以要加一层判断:

class  Single
{
private static Single s = null;
private Single(){}
public static Single getInstance()
{
if(s==null)
{
synchronized(Single.class)
{
if(s==null)
s = new Single();
}
}
return s;

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息