------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
1.同步函数使用的锁是this锁
2.如果同步函数被静态修饰后,使用的锁是什么?静态进内存是,内存中没有本类对象,但是一定有该类对象对应的字节码文件对象
类名.class 该对象的类型是Class
静态的同步方法,使用的锁是该方法所在类的字节码文件对象 类名.class
3.懒汉式:延迟加载的单例设计模式
缺点:多线程访问时,可能引起线程安全问题
解决方式:加同步锁(而且用双重判断提高效率)
/* 饿汉式(解决了线程安全问题)
*/
class Single
{
private static Single s = null;
private Single(){}
public static Single getInstance()
{
if(s == null)
{
/* 如果线程B停在这里 s = null;
而线程A 在锁里执行完 s = new Single();
但是线程B 获得锁后,还会再次 new Single();
synchronized(Single.class)
{
s = new Single();
}
*/
synchronized(Single.class)
{
if(s == null)
{
s = new Single();
}
}
}
}
}
4.
/*
死锁的一个例子
*/
class DeadLockDemo
{
public static void main(String[] args)
{
Thread t1 = new Thread(new DeadLock(true));
Thread t2 = new Thread(new DeadLock(false));
t1.start();
t2.start();
}
}
class DeadLock implements Runnable
{
private boolean flag = true;
public DeadLock (boolean flag)
{
this.flag = flag;
}
public void run()
{
if(flag) {
synchronized(MyLock.o1)
{
System.out.println("if o1") ;
synchronized(MyLock.o2)
{
System.out.println("if o2") ;
}
}
} else {
synchronized(MyLock.o2)
{
System.out.println("else o2") ;
synchronized(MyLock.o1)
{
System.out.println("else o1") ;
}
}
}
}
}
class MyLock
{
static Object o1 = new Object();
static Object o2 = new Object();
}
5.线程间通信
其实就是多个线程在操作同一个资源,但是操作的动作不同。
6.wait() ,notify(); notifyAll();
都使用在同步中,因为要对持有监视器(锁)的线程操作
所以要使用在同步中,因为只有同步才具有锁。
为什么这些操作线程的方法要定义在Object类中呢?
因为这些方法在操作同步线程时,都必须要标识他们所操作线程只有的锁。
只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒、
不可以对不同锁中的线程进行唤醒。
也就是说,等待和唤醒必须是同一锁。
而锁可以使任意对象,所以可以被任意对象调用的方法定义在Object中。
7.
/*
对于多个生产者和消费者时
为什么要定义while判断标记?
原因:让被唤醒的线程再一次判断标记。
为什么定义notifyAll
因为需要唤醒对方线程。
因为只有notify,容易出现只唤醒本方线程的情况,导致程序中的所有线程都等待。
*/
class ProducerConsumer
{
public static void main(String[] args)
{
Resource r = new Resource();
Producer p = new Producer(r);
Consumer c = new Consumer(r);
Thread t1 = new Thread(p);
t1.start();
Thread t2 = new Thread(c);
t2.start();
Thread t3 = new Thread(p);
t3.start();
Thread t4 = new Thread(c);
t4.start();
}
}
class Resource
{
private String name;
private int count = 1;
private boolean flag = false;
public synchronized void set(String name)
{
//当等待结束后,会再次判断flag
while(flag)
{
try{this.wait();}catch(Exception e){}
}
this.name = name+"---"+(count++);
System.out.println(Thread.currentThread().getName()+"生产者--"+this.name);
flag = true;
this.notifyAll();
}
public synchronized void out()
{
while(!flag) {
try{this.wait();}catch(Exception e){}
}
System.out.println(Thread.currentThread().getName()+"消费者---------"+name);
flag = false;
this.notifyAll();
}
}
class Producer implements Runnable
{
private Resource re;
Producer(Resource re)
{
this.re = re;
}
public void run ()
{
while(true)
{
re.set("商品");
}
}
}
class Consumer implements Runnable
{
private Resource re;
Consumer(Resource re)
{
this.re = re;
}
public void run ()
{
while(true)
{
re.out();
}
}
}
8.JDK1.5中提供了多线程升级解决方案
将同步sychronized 替换成现实Lock操作
将Object中的wait,notify notifyAll替换成了Condition对象
该对象可以Lock锁,进行获取。
可以只唤醒对方操作。
10.停止线程
stop方法已经过时。
如何停止线程呢?
只有一种,run方法结束。
开启多线程运行,运行代码通常是循环结构的。
只要控制住循环,就可以让run方法结束。也就是线程结束。
特殊情况:
当线程处于冻结状态。
就不会读取到标记。那么线程就不会结束。
当没有指定的方法让冻结的线程恢复到运行状态时,这时需要对冻结进行清除。interrupt()
强制让线程恢复到运行状态中来。
class StopThreadDemo
{
public static void main(String[] args)
{
StopThread s = new StopThread();
Thread t1 = new Thread(s);
Thread t2 = new Thread(s);
t1.start();
t2.start();
int x = 0;
while(true)
{
if(x++ == 60)
{
t1.interrupt();
t2.interrupt();
break;
}
System.out.println(Thread.currentThread().getName()+"..main.."+x);
}
}
}
class StopThread implements Runnable
{
boolean flag = true;
public synchronized void run()
{
while(flag)
{
try {
wait();
} catch(InterruptedException e) {
flag = false;
System.out.println(Thread.currentThread().getName()+"..exception..");
}
System.out.println(Thread.currentThread().getName()+"..run..");
}
}
}
11. t.join(); 该线程抢占cpu,他结束后别人才能运行。
特点:当A线程执行到了B线程的join方法时,
A线程就会等待,B结束后A才会执行。
join可以临时加入线程执行。