多线程

来源:互联网 发布:python pd.to numeric 编辑:程序博客网 时间:2024/04/29 16:12
------- android培训、java培训、期待与您交流! ----------

1.进程: 正在执行中的程序

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

2.线程:进程中的一个独立的控制单元 

     线程在控制着进程的执行

         每一个进程中至少有一个线程

3.扩展:

a) JAVA VM启动时会有一个进程,叫JAVA .EXE 该进程中至少有一个线程在负责JAVA程序的执行,而且这个线程,运行的代码存在于MAIN方法中。该线程称之为主线程。

b)  JVM 启动时不止一个线程,还有负责垃圾回收机制的线程。

4.创建线程的第一种方式 继承THREAD类,覆盖RUN方法 创建该类对象执行START()方法。

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

 b)明确一点在同一时刻,只能有一个线程运行。(多核除外)cpu在做着快速的切换以达到看上去同时运行的效果。 

c)我们可以形象地把多线程运行看成是在互相抢夺CPU的资源。多线程的这个特性叫做随机性。至于执行时间由CPU控制。

5.线程的5种状态
 

本地图片,请重新上传

6. 创建线程的第二种方式 RUNABLE接口

a) 定义类,实现RUNABLE接口

b) 覆盖RUNABLE接口中的RUN()方法

c) 通过THREAD类建立线程对象

d) RUNABLE的实现对象作为实参传递给Thread的构造函数

e) 调用Thread类的Start()方法开启线程并调用接口子类的Run方法

7.两种方式的区别

实现方式和继承方式的区别

线程代码存放的位置不一样

继承:线程代码存放在T的子类中

实现:线程代码存放在R接口子类中

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

8.多线程的安全问题

a) 无锁的情况下,会出现安全问题

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

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

d) JAVA对于多线程安全问题提供了同步代码块。

synchronized(对象)
{

需要被同步的代码

}

e)代码如下:

public class TicketTest1 implements Runnable 

{

private int tick=100;

private int count=0;

Object obj=new Object();

public void run()

{

while(true)

{

synchronized(obj)

{

if(tick>0)

{

System.out.println(Thread.currentThread().getName()+"---"+tick--);

count++;

}

else

{

System.out.println(Thread.currentThread().getName()+"end-----"+count);

break;

}

}

}

}

public static void main(String[] args) 

{

TicketTest1 t=new TicketTest1();

Thread t1=new Thread(t);

Thread t2=new Thread(t);

Thread t3=new Thread(t);

Thread t4=new Thread(t);

t1.start();

t2.start();

t3.start();

t4.start();

}

}

f)对象如同锁,持有锁的线程可以在同步代码块中执行

g)同步的前提

a) 必须要有2个以上的线程才需要同步

b) 必须是多个线程使用同一个锁

必须保证同步当中只有一个线程在运行

h)利弊

i. 利:解决了多线程的安全问题

ii. 弊:多个线程都需要判断锁,较为消耗资源。

i)同步函数使用的锁是THIS,静态同步函数使用的锁是  类名.CLASS 该类的字节码对象

public class LockTest implements Runnable 

{

private int tick=1000;

private int count=0;

Object obj=new Object();

boolean flag=true;

public void run()

{

if(flag)

{

while(true)

{

synchronized(this)

{

if(tick>0)

{

System.out.println(Thread.currentThread().getName()+"---"+tick--);

count++;

}

else

{

System.out.println(Thread.currentThread().getName()+"end-----"+count);

break;

}

}

}

}

else

{

this.show();

}

}

public synchronized void show()

{

while(true)

{

if(tick>0)

{

System.out.println(Thread.currentThread().getName()+"---"+tick--);

count++;

}

else

{

System.out.println(Thread.currentThread().getName()+"end-----"+count);

break;

}

}

}

public static void main(String[] args) 

{

LockTest t=new LockTest();

Thread t1=new Thread(t);

Thread t2=new Thread(t);

t1.start();

try 

{

Thread.currentThread().sleep(1);

}

catch (InterruptedException e) 

{

e.printStackTrace();

}

t.flag=false;

t2.start();

}

}

9.单例设计模式

//饿汉式

//class Single

//{

//private static final 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(null==s)

{

synchronized(Single.class)

{

if(null==s)

{

s=new Single();

}

}

}

return s;

}

}

10.死锁

a)同步中嵌套同步,而锁却不同

b)死锁代码

public class DeadLockTest1 

{

public static void main(String[] args)

{

Lock l1=new Lock(true);

Lock l2=new Lock(false);

Thread t1=new Thread(l1);

Thread t2=new Thread(l2);

t1.start();

t2.start();

}

}

class MyLock

{

static Object locka=new Object();

static Object lockb=new Object();

}

class Lock implements Runnable

{

private boolean flag=false;

public Lock(boolean flag)

{

this.flag=flag;

}

public void run()

{

if(flag)

{

while(true)

{

synchronized(MyLock.locka)

{

System.out.println("if a locked");

synchronized(MyLock.lockb)

{

System.out.println("if b locked");

}

}

}

}

else

{

while(true)

{

synchronized(MyLock.lockb)

{

System.out.println("else  b locked");

synchronized(MyLock.locka)

{

System.out.println("else  a locked");

}

}

}

}

}

}

11.同步线程间的通信--等待唤醒机制

a)wait() notify() notifyAll() 都使用在同步中,因为要对持有锁的线程操作,而只有同步才会有锁,所以要使用在同步中。

b)上述方法为何要定义在OBJECT中 因为这些方法在操作同步线程时,都必须要标识所操作线程持有的锁,只有同一个锁上的被等待线程可以被同一个锁上的NOTIFY唤醒,不可以对不同锁中的线程进行唤醒。等待和唤醒针对的是同一个锁,而锁可以是任意对象。

c)优化后的通信代码

package com.itheima.thread;

public class InputOutputDemo 

{

public static void main(String[] args) 

{

Res r=new Res();

new Thread(new Input(r)).start();

new Thread(new Output(r)).start();

}

}

class Res

{

private String name;

private String sex;

private boolean flag;

public synchronized void reset(String name, String sex) 

{

if(flag)

{

try

{

wait();

}

catch (InterruptedException e) 

{

e.printStackTrace();

}

}

this.name = name;

this.sex = sex;

flag=true;

notify();

}

public synchronized void show()

{

if(!flag)

{

try 

{

wait();

}

catch (InterruptedException e) 

{

e.printStackTrace();

}

}

System.out.println(name+"........."+sex);

flag=false;

notify();

}

}

class Input implements Runnable

{

private Res r;

public Input(Res r)

{

this.r=r;

}

public void run() 

{

int x=0;

while(true)

{

if(0==x%2)

{

r.reset("tom","male");

}

else

{

r.reset("张三","男男男男男");

}

x++;

}

}

}

class Output implements Runnable

{

private Res r;

public Output(Res r)

{

this.r=r;

}

public void run() 

{

while(true)

{

r.show();

}

}

}

d)多个线程通信 WHILE(FLAG) &  NITIFYALL(); 防止全部冻结

class Resource

{

private String name;

private int count=1;

private boolean flag=false;

public synchronized void set(String name)

{

while(flag)

{

try 

{

wait();

}

catch (Exception e) 

{

e.printStackTrace();

}

}

this.name=name+"--"+count++;

System.out.println(Thread.currentThread().getName()+"...生产者...           "+this.name);

flag=true;

notifyAll();

}

public synchronized void show()

{

while(!flag)

{

try 

{

wait();

}

catch (Exception e) 

{

e.printStackTrace();

}

}

System.out.println(Thread.currentThread().getName()+"...消费者...           -----"+this.name);

flag=false;

notifyAll(); //唤醒了全部的等待线程

}

}

e)1.5新特性 (多线程升级解决方案 ) 

1.SYNCHRONIZED LOCK UNLOCK  (显式锁)TIP:一定要释放锁

2.OBJECT WAIT NOTIFY NOTIFYALL  CONDITION 通过LOCK获取 可以有多个CONDITION对象  从而实现本方只唤醒对方的操作  

完整代码

package com.itheima.thread1;

public class ProducerConsumerDemo 

{

public static void main(String[] args) 

{

Resource res=new Resource();

new Thread(new Producer(res)).start();

new Thread(new Producer(res)).start();

new Thread(new Consumer(res)).start();

new Thread(new Consumer(res)).start();

}

}

class Resource

{

private String name;

private int count=1;

private boolean flag=false;

public synchronized void set(String name)

{

while(flag)

{

try 

{

wait();

}

catch (Exception e) 

{

e.printStackTrace();

}

}

this.name=name+"--"+count++;

System.out.println(Thread.currentThread().getName()+"...生产者...           "+this.name);

flag=true;

notifyAll();

}

public synchronized void show()

{

while(!flag)

{

try 

{

wait();

}

catch (Exception e) 

{

e.printStackTrace();

}

}

System.out.println(Thread.currentThread().getName()+"...消费者...           -----"+this.name);

flag=false;

notifyAll();

}

}

class Producer implements Runnable

{

private Resource res;

public Producer(Resource res)

{

this.res=res;

}

public void run()

{

while(true)

{

res.set("商品");

}

}

}

class Consumer implements Runnable

{

private Resource res;

public Consumer(Resource res)

{

this.res=res;

}

public void run()

{

while(true)

{

res.show();

}

}

}

12.停止线程

a) STOP方法已经过时 只有一种停止方式 RUN()方法执行完毕

b) 开启多线程,运行代码通常都是循环结构,终止循环即终止了线程

c) 特殊情况: 当线程处于冻结状态,就不会读取到标记,就不会结束

d) Interrput() 中断线程 当进入冻结状态时,消除冻结状态,强制恢复到运行状态

e) 当没有指定的方式让冻结的线程恢复到运行状态时,这时就需要对冻结进行消除。强制让线程恢复到运行状态中,从而操作标记让线程结束。

13.setDaemo(boolean on)  后台线程(开启后和前台线程共同运行,当所有前台线程结束后,后台线程会自动结束)

a) 将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时JAVA虚拟机将退出。

b) 该方法必须在启动线程前使用

c) 该方法首先调用该线程的checkAccess方法,且不带任何参数。当前线程无法修改时,可能抛出SecurityException

14.join() 等待该线程终止

a) 申请加入到运行中,要CPU执行权

b) A线程执行到了B线程的JOIN方法时,A线程在B线程执行完后才执行

c) 可以加入临时线程

15.线程组,很少用,谁开启则属于哪个组

16.优先级 PRIORITY 默认为5 1-10 MAX MIN Thread.NORM_PRIORITY

a) setPriority(int newPriority)

17.yield()

a) 暂停当前线程,并执行其他线程

b) 稍微减少执行的频率,如果有两个线程,达到类似交替执行的效果