Java线程



第九章 Java线程
一.线程的概述;
1.程序:程序是一段静态的代码,它是应用程序执行的蓝本
2.进程:进程是指一种正在运行的程序,有自己的地址空间
3.线程:在进程的基础上进行多个分支操作;独立运行;
线程的定义:
进程是系统资源分配的单位,可包括多个线程
线程是独立调度和分派的基本单位,共享进程资源
引入进程是为了多个程序并发执行,提高资源的利用率和系统吞吐量
引入线程是为了减少程序在并发执行时付出的时空开销
4.进程的特点:
动态性 
并发性 
独立性 
5.多进程:多进程是在某种程度上相互隔离的,独立运行的程序;
6.多线程:将任务的划分,下降到了程序的级别;


7.线程的优势:
a.线程在程序中使独立的,并发的执行流;
b.但是与隔离的进行相比,进程中的线程之间的隔离程度较小。他们共享内存;
c.多个线程将共享同一个京城的虚拟空间,线程共享的包括:线程代码,进程的公共数据 等等;
d.具体总结:
1.多线程使系统空转时间减少,提高CPU利用率
2.进程间不能共享内存,但线程之间共享内存非常容易
3.使用多线程实现多任务并发比多进程的效率高
4.Java语言内置多线程功能支持,简化了Java的多线程编程
二.Java线程模型
1.程序可运行的三个要素:CUP 程序代码 可存取的数据(内存);
将一个线程看作一个程序的主线程看;(虚拟的:CUP 程序代码 可存取的数据(内存))
三.创建线程
1.创建方式一
a.在java中创建线程的一种方式是通过:Thread来实现;
public class Thread 
extends Object 
implements Runnable
将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。
多个构造方法:
(1)Thread() :分配(创建)新的 Thread 对象。
(2)Thread(Runnable target) :创建一个线程,并指定一个目标;
(3)Thread(Runnable target, String name) :创建一个名为name的目标为target的线程;
(4)Thread(ThreadGroup group, Runnable target, String name) :
新的 Thread 对象,以便将 target 作为其运行对象,将指定的 name 作为其名称,
并作为 group 所引用的线程组的一员。
方法:
start():使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
调用start方法并不一定马上执行;


2.创建方式二
a.实现 Runnable 接口的类。该类然后实现 run 方法。
然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动
//通过实例化某个 Thread 实例并将自身作为运行目标,
3.两种方式的比较
a.使用Runnable接口;
可以将CUP,代码和数据分开,形成清晰的模型;
还可以从其他类继承
保持程序风格一致;
b.直接继承Thread类
不能再继承其他类
编写简单,可以直接操作线程;


3.后台线程;
有一种线程,他在后台运行;他的任务是为其他的线程提供服务;这种线程叫做;后台线程;
或是“守护线程”
后台线程的优先级低于其他线程;
方法:
setDaemon(boolean on) : 将该线程标记为守护线程或用户线程。
boolean isDaemon() :测试该线程是否为守护线程。




四,线程的状态
1.线程的基本状态
五种:
新建(New),可运行(Runnable),运行(Running),阻塞(Blocked),死亡(Dead),
阻塞状态:原因调用sleep()方法:调用对象的wait()方法,
当sleep();方法睡眠时间到后,或则其他线程调用了对象的notify();notfyAll();方法唤醒等待的线程;
currentThread() :返回对当前正在执行的线程对象的引用。
boolean isAlive() :测试线程是否处于活动状态。


2.线程的结束方式;
(1)线程到达run方法的末尾;
(2)线程抛出一个未捕获的异常,或错误
(3)另一个线程调用Deprecated的stop方法;因为这个方法在线程中会引起线程安全问题,所以,不要再程序调用这个方法;
五.线程控制
1.测试线程
boolean isAlive() :测试线程是否处于活动状态。
活跃状态并不代表处于Running状态;
2.中断线程;
Thread.sleep();线程暂时停止实行睡眠一段时间
Thread.yield();线程放弃运行,将CPU的控制权让出;
一个线程在执行一个很长的循环时,需要适当的调用sleep或则yield(),让出CUP共其他线程运行;
如果不遵循这个原则的线程叫做:利己线程;
3.设置线程的优先级
getPriotity();获取线程的优先级别;
setPriority();设置线程运行的优先级别;
  NORM_PRIORITY 
          分配给线程的默认优先级。
 MIN_PRIORITY 
          线程可以具有的最低优先级。
 MAX_PRIORITY 
          线程可以具有的最高优先级。
六,线程的join方法;
调用Thread.join()方法时。调用线程将被阻止,直到被调用join方法加入到目标线程执行完为止;
七.多线程编程
1.多线程概述;
概念:在主线程中有多个线程在运行;
2.多线程共享数据
用银行卡取钱的例子;共享数据为卡中的钱;
3.互斥锁
a.java中引入了“对象互斥锁”(mutual exclusice lock)简称“对象锁”,
作用:保证共享数据操作的完整性;
b.关键字
(1).synchronized用来与对象的互斥锁联系;
每一个对象都对应一个可称为:“互斥锁”的标记;
这个标记用来保证在任意时刻只能由一个线程访问该对象;
(2)当某个对象用synchronized修饰时,表明该对象在任意时刻只能由一个线程访问;
c.java中两种使用synchronized的方式;
(1)放在方法前面。这样,调用该方法的线程均将获得对象的锁;
(2)放在代码块前面。用于修饰对象的引用,
a.用于修饰当前对象synchronized(this){}或则synchronized{}
代码块中的代码将获得当前对象的引用锁;
b.用于修饰当前制定的对象 synchronized(OtherObject);
代码块中的代码将获得指定对象的引用锁;
注意:synchronized锁定的不是方法或则代码块,而是对象;
当synchronized被当作方法的修饰符时:
方法所取得的对象锁将被转交给方法调用者;
当synchronized修饰对象引用时:
则取得对象锁将交给该引用所指向的对象;
d.对一个对象进行同步控制意味着:
调用该方法的线程将会取得该对象的“锁”;当:“线程主卡”获得对象money对象锁,就意味着
其他线程通过synchronized申请对money进行访问线程,在“线程主卡”没有释放该对象money的时候,
其他线程无法访问;
e.synchronized可以修饰类;
当将synchronized用在类前面时;就表示这个类的所有方法都是synchronized来修饰;

f.如果一个线程一直占用这个对象锁,则其他线程将无法访问这个对象;
在适当的时候应将对象锁归还;
线程归还对象锁的时机:
(1)当线程执行到synchronized块结束时;
(2)当在synchronized块遇到break;return或则抛出异常,则自动释放对象锁;
(3)当这个线程调用wait()方法时;它放弃所有的对象锁,并进入等待队列;
4.死锁;
死锁:指两个线程都互相等待对方释放lock;
5.线程之间通信;
生产者和消费者问题:
(1)假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中产品取走
(2)如果仓库中没有产品,则生产者将产品放入仓库,否则停止生产并等待,直到仓库中的产品被消费者取走为止
(3)如果仓库中放有产品,则消费者可以将产品取走消费,否则停止消费并等待,直到仓库中再次放入产品为止
方法:
final void wait();表示线程一直等待,直到其它线程通知
void wait(long timeout);线程等待指定毫秒参数的时间
final void wait(long timeout,int nanos);线程等待指定毫秒、额外的时间
final void notify();唤醒一个处于等待状态的线程
final void notifyAll():唤醒同一个对象上所有调用wait()方法的线程,优先级别高的线程优先运行
八.定时器
1.在java.util包中,有两个类和定时相关;
a.Timer
Timer是一个定时器;他可以定时执行一些任务;
b.TimerTask
TimerTask:所有定时执行的任务都是由TimerTask定义;
2.类 Timer 
Timer中有四个重载的schedule()方法;
a.schedule(TimerTask tt,Date date):在指定的时间date执行TimerTask所制定的任务;
b.schedule(TimerTask tt,Date date,long period):在指定的时间date开始第一次执行TimerTask的任务,每隔period时间(毫秒)重复;
c.schedule(TimerTask tt,long delay):在指定时间delay(单位:毫秒)后执行TimerTask制定任务;
d.schedule(TimerTask tt,long delay,long period):在指定时间delay(单位:毫秒)后执行TimerTask制定任务;每隔period时间(毫秒)重复;


3.java.util 类 TimerTask
实现的接口: Runnable ;基本上是一个线程
方法:run() :此计时器任务要执行的操作。
将要定时执行的任务放在run()方法中;
然后TimerTask作为Timer对象的schedule()方法的参数,他会定时执行这个TimerTask所定义的任务;


4.步骤
a.定义一个类,让它继承TimerTask,并且将需要定时执行的动作定义到run()方法中;
b.实例化一个Timer对象,然后,将上面定义的TimerTask对象作为Timer对象schedule()方法参数,并在这个方法中设置定时排程;






九.多线程编程的一般规则
1.如果两个或两个以上的线程都修改一个对象,那么把执行修改的方法定义为同步的,
如果对象更新影响到只读方法;那么只读方法也定义为同步;
2.如果一个线程必须等待一个对象状态变化,那么他就应该在对象内部等待,
而不是在外部,他可以通过调用一个被同步的方法,并且让这个方法调用wait();
3.当一个方法返回某一个对象的锁时,它应该调用notify()或则notifyAll来让其他线程有执行的机会;
4.仔细查看每一次调用的wait()方法;使得她都有相应的notify()或者notifyAll()方法,且他们均作用于同一个对象;
5.针对使用wait(),notifyAll(),notify()使用旋锁;
6.优先使用notifyAll();而不是notify();
7.按照固定的顺序获得多个对象锁,以避免死锁;
8.不要对上锁的对象改变他的引用;
9.不要滥用同步机制,避免无所谓Udell同步控制;






































































































































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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值