黑马程序员--05--多线程技术

黑马程序员--05--多线程技术
                                                            -------  android培训 java培训 、期待与您交流! ----------
图片
/*
进程:
每个正在执行的程序都称为进程。

线程:
线程是进程里面的一个控制单元,一个进程中至少有一个线程。线程在被创建之后都放在一个线程池中,wait的时候也在线程池中,使用notifyAll()方法可以唤醒所有的wait()的线程。
多线程:
多线程就是一个进程里面包含多个线程,这样就使一个进程可以同时执行多个功能。
单核CPU的计算机同时运行多个功能并不是CPU同时执行的,而是CPU通过高速切换执行的,以达到多个功能同时运行的效果,CPU在某一时刻只能执行一个线程,而不是多个同时执行。

 JVM就是一个多线程程序,一个是主函数的线程,一个是垃圾回收站的线程。
 
 在java中创建多线程的方法有两个:
  1、通过继承Thread类,重写run()方法。
  2、实现Runnable接口中的run()方法。
 
 在实现了多线程代码之后只需要使用start()方法即可,start()方法调用了run()方法,因此无需手动调用run()方法。

线程的五种状态:新建状态、就绪状态、运行状态、阻塞状态、死亡状态
新建状态:创建了一个线程,但它没有启动,处于新建状态的线程对象,只能被启动或者终止。例如:Thread t = new Thread();
就绪状态:就绪状态处于正在等待CPU资源的状态,具备了可执行的能力。例如:t.start();
运行状态:已经获得了CPU资源,正在运行的状态。
阻塞状态:正在执行的线程遇到某个特殊情况(例如延迟、挂起、等待I/O操作完成等)让出自己的CPU资源,并暂时停止自己的执行。
死亡状态:线程没有继续运行的能力,也不能再转到其他状态。

继承Thread与实现Runnable的区别:
1、继承了Thread就不能再继承其他类了,而实现了Runnable还可以继承其他类。所以一般推荐使用Runnable实现多线程。
2、继承Thread类实现的代码存放在Thread子类的run方法中,Runnable实现的代码存放在Runnable的子类接口中。

在多线程中最主要的问题就是线程安全问题,java中提供了专业的解决方法:Synchronized线程同步。

同步的两种表现形式:
1、同步函数public synchronized void method();非静态同步函数中使用的锁是this,静态函数的锁是类的字节码文件"类名.class"。
2、同步代码块synchronized(对象){需要被同步的代码块}。同步代码块中使用的锁是程序员传递的对象。

那些在执行共享数据的代码就同步那些。
对象如同锁,持有锁的线程可以执行同步代码块的语句。没有锁的线程及时有CPU的执行权也不能执行同步代码块的内容。
同步的前提:
1、必须有两个或两个以上的线程。
2、必须是多个线程使用同一个锁。
3、必须保证同步中只有一个线程。

死锁:
同步中嵌套同步出现的问题。
同步锁的弊端:每个线程每次执行到同步代码块前都要先判断一次锁,所以会降低执行效率,较为消耗资源。

线程间通讯:
其实就是多个线程在操作同一资源,只是操作的方式不同。
线程间通信常使用的方法有:wait()、notify()、notifyAll()。
wait()、notify()、notifyAll()方法只能在同步代码块或同步方法中使用,因为要对持有监视器(锁)的线程操作,只有同步才具有锁。
为什么这些方法要定义在Object类中?因为这些方法要标识持有的锁"Lock.wait()",只有同一个锁上的线程才能被同一个锁上的另一个线程唤醒,而且只有Object的方法才能被任意对象调用。
当使用两个以上的线程操作统一数据时要使用while进行标记判断和notifyAll唤醒所有线程,例如:生产和消费的示例。

停止线程的方法:
接收run()方法。开启多线程通常都是循环结构的,只要定义一个结束标记让线程进行判断就可以结束run()方法,也就是结束线程。
特殊情况:当线程处于阻塞状态就不会读取到结束标记,这时需要使用interrupt()强制唤醒线程去判断结束标记。
守护线程:
被设置为守护线程的线程会在所有线程结束后自动结束,运行时和其它线程没区别。就像进程与线程一样,线程就是守护线程,进程就是守护线程外的线程,只有进程结束,线程就会结束。

当某个线程执行到A.join()方法时会将它的执行权先让出来先让A这个线程执行完。
*/

//实现多线程的两种方法示例
class NewThread1 extends Thread
{
NewThread1(String name)
{
super(name);
}
public void run()
{
Thread t = Thread.currentThread(); //获取当前的线程
try
{
t.sleep(1000); //使线程睡眠1000毫秒
}
catch(InterruptedException e)
{
System.out.println("线程睡不着。");
}
t.setPriority(t.MAX_PRIORITY); //设置优先权MAX_PRIORITY、MIN_PRIORITY、NORM_PRIORITY 
System.out.println(t.getName()+"---信息:"+t.toString()); //打印当前线程的陈述
System.out.println("名字:"+t.getName()); //获取名字
System.out.println(t.getName()+"---ID:"+t.getId()); //获取ID
System.out.println(t.getName()+"---优先权:"+t.getPriority()); //获取优先权
System.out.println(t.getName()+"---是否活着:"+t.isAlive()); //判断线程是否活着
t.interrupt(); //强制唤醒当前线程
System.out.println(t.getName()+"---线程是否被中断:"+t.isInterrupted());  //判断线程是否被中断
System.out.println(t.getName()+"---状态:"+t.getState()); //获取状态
}
}

class NewThread2 implements Runnable
{
public void run()
{
try
{
Thread.currentThread().sleep(2000);
}
catch(InterruptedException e)
{
System.out.println("线程睡不着!");
}
Thread.currentThread().setName("t2--线程"); //给线程自定义名称
System.out.println(Thread.currentThread().getName()+"------线程ID:"+Thread.currentThread().getId());
System.out.println("线程名字:"+Thread.currentThread().getName());
}
}

public class ThreadDemo
{
public static void main(String args[])
{
NewThread1 t1 = new NewThread1("t1--线程");
t1.start(); //启动线程
NewThread2 t2 = new NewThread2();
new Thread(t2).start();
System.out.println("主线程OVER!");
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值