黑马程序员_多线程
来源:互联网 发布:nginx 地址反向代理 编辑:程序博客网 时间:2024/05/14 05:48
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------
进程就是一个正在执行中的程序;每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元;线程就是进程中一个独立的控制单元,控制着进程的执行;一个进程中至少有一个线程;而多线程就是 一个进程中有可能存在多条执行路径。
如何在自定义的代码中,自定义一个线程呢?
方法一:
1、继承Thread类
2、复写Thread类中的run方法
3、调用线程的start方法(启动线程,调用run方法)
eg:
class Demo extends Thread //继承Thread类
{
public void run() //复写Thread类中的run方法
{
for(int x=0;x<60;x++)
System.out.println("demo run----"+x);
}
}
class ThreadDemo
{
public static void main(String[] args)
{
Demo d=new Demo(); //创建好一个线程
d.start(); //启动线程,并调用run方法。
for(int x=0;x<60;x++) //主线程为了达到对比效果,也做循环输出语句
System.out.println("Hello World!--"+x);
}
}
PS:由于某一时刻执行哪个线程是cpu说了算,所以每次的打印结果都是不同的。这是多线程的一个特性:随机性。
线程有四种基本状态:
1、被创建
2、运行(start())
3、冻结(等待,睡眠。。)sleep(time)时间到了复活;wait()-notify()叫醒复活;
4、消亡(stop()或方法结束,注意:stop()方法已过时; )
特殊状态:临时状态(阻塞状态),具备运行资格,但没有执行权
获取线程对象以及名称:Thread.currentThread().getName(原来线程都有自己默认的对象,从Thread0开始)
创建线程方法二:实现Runnable接口
步骤:
1、定义类实现Runnable接口
2、覆盖Runnable接口中的run方法(将线程要运行的代码存放在该run方法中)
3、通过Thread类建立线程对象
4、将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数
5、调用Thread类的start方法开启线程,并调用Runnable接口子类的run方法
两种方式的区别:
继承Thread:线程代码存放Thread子类run方法中
实现Runnable,线程代码存在在接口的子类的run方法中
实现Runnable接口的好处是:
除接口外,java是不支持多继承的,而若用第一种方法,继承Thread类创建线程,则无法再继承其他类,为编程造成很多困扰和不便。
通过分析发现,多线程可能会出现安全问题
问题的原因:
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行,导致了共享数据的错误。
解决办法:
对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与运行。(即锁)
5.0版本更新后,JDK1.5中提供了多线程升级解决方案:
将同步Synchronized替换成显示的Lock操作。
将Object中的wait,notify,notifyAll替换成了Condition对象。
升级版可以支持多个相关的Conditon对象
多线程同步代码块的前提:
1、必须要有两个或者两个以上的线程
2、必须是多个线程使用同一个锁
好处:解决了多线程的安全问题
弊端:多个线程都需要判断所,较为消耗资源
当多线程出现问题时,如何寻找呢?
1、哪些是多线程运行代码
2、明确共享数据
3、明确多线程运行中哪些语句是操作共享数据的
同步有两种表现形式:同步函数和同步代码块,其中同步函数要更简单。
加入多线程的考虑,回顾单例式:
//饿汉式
class Single
{
private static final Single s = new Single(); //只需加关键字final即可,只能创建一次。
private Single(){}
public static Single getInstance()
{
return s;
}
}
//懒汉式
class Single
{
private static Single s = null;
private Single(){}
public static Single getInstance()
{
if(s==null) //锁前先判断,一定程度提高了效率
{
synchronized(Single.class) //以类名.class为唯一锁
{
if(s==null) //判断两次
//--->A;
s = new Single();
}
}
return s;
}
}
由此可见,饿汉式更为简单方便,且单例模式为的就是调用其中的那个唯一的对象,所以,饿汉式应用的也更为普遍。
死锁的问题:
同步中嵌套同步,而锁却不同,很容易产生死锁现象。
线程间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同。为解决安全问题,出现了等待唤醒机制。
conditon.await(); //等待
conditon.signalAll(); //唤醒所有
由于stop过时,要停止线程应如何操作呢?
定义循环结束标记
因为线程运行代码一般都是循环,只要控制了循环即可。
使用interrupt(中断)方法
该方法时结束线程的冻结状态,使线程回到运行状态中来。
Eg:
class StopThread implements Runnable
{
private boolean flag =true; //定义标记变量
public void run() //覆写run方法
{
while(flag)
{
System.out.println(Thread.currentThread().getName()+"....run");
}
}
public void changeFlag() //如函数名一样,修改标记变量的值
{
flag = false;
}
}
class StopThreadDemo //终止线程的小例子
{
public static void main(String[] args)
{
StopThread st = new StopThread();
Thread t1 = new Thread(st); //创建了两个线程(都是Thread的子类)
Thread t2 = new Thread(st);
//t1.setDaemon(true);
//t2.setDaemon(true);
/*这里的setDaemon为设置守护线程,当所有线程都为守护线程时,JVM会自动退出。
就像圣斗士星矢一样,圣斗士都是守护者守护着雅典娜,若没有了雅典娜,动画片中的
五位圣斗士也就失去了存在的价值。若不注释掉两句设置守护线程的代码,则无需去
run中判断,java虚拟机会直接退出。*/
t1.start(); //启动两个建立好的线程
t2.start();
int num = 0; //计数便于观察和理解
while(true)
//循环判断,若非如此,容易出现多个生产者和消费者不一一对应的情况。
{
if(num++ == 60)
{
//st.changeFlag();
//t1.interrupt();
/*中断机制,将处于冻结状态的线程,强制恢复到运行状态中。非正常苏醒状态,比如
一个人被催眠后,催眠师出国了,毕老师狠劲一拳将其打醒,随然也达到了叫醒的
目的,但会受伤。即抛出异常:InterruptedException*/
//t2.interrupt();
break;
}
System.out.println(Thread.currentThread().getName()+"......."+num);
}
System.out.println("over");
}
}
其它小知识点:
Join方法:当A线程执行到了B线程的.join()方法时,A就会等待。等B线程都执行完,A才会执行。(join可以用来临时加入线程执行。申请执行权)
优先级:线程的默认优先级都是5,包括主线程,一共十级。setPriority()用于更改线程的优先级,优先级越高,cpu执行该线程的频率越高,但不会不管其他线程。
yield()方法:暂停当前正在执行的线程对象,并执行其他线程。(临时停止)
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- YUV YCbCr 区别
- ztree 使用小结 (两级联动)
- 检测网络四部曲
- android多国语言文件夹文件汇总
- 段寄存器引用规定
- 黑马程序员_多线程
- eclipse
- TCHAR, WCHAR, LPSTR, LPWSTR, LPCTSTR 之间的联系与区别
- 超强版系统垃圾清理批处理
- 去掉gridview 黄色背景
- vi常用参考
- 开源的projection mapping项目
- 64位多核 MIPS 异常和中断内核代码分析 (4)
- Cygwin + NS2 + Win XP 安装方法 网上 唯一 有效版!