多线程
来源:互联网 发布:python pd.to numeric 编辑:程序博客网 时间:2024/04/29 16:12
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) 稍微减少执行的频率,如果有两个线程,达到类似交替执行的效果- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 对Memcached使用的总结和使用场景
- centos中的分区
- curl shell 用法
- 包导入
- 广州传智播客0615JAVA就业班体育活动
- 多线程
- Hadoop2-MapReduce(2)
- 【全方面预防U盘病毒侵入】
- 论《如何打通软件人员的上升通道》
- 算法导论 第7章部分习题解答
- How does TestFlight do it?(分发测试版本可以用到的一些工具和代码)
- 交通灯系统
- The Most Important Algorithms
- 创建struct fib_info函数分析