十三章总结

第十三章总结

一、进程和线程

1、程序:一段静态的代码

2、进程:程序的一次动态执行过程它对应从代码加载、执行到执行完毕的一个完整过程。

3、进程也称任务,支持多个进程同时执行的os就被称为多进程os或多个任务os。

4、在一个程序内部也可以实现多个任务并发执行,其中每个任务称为线程。

5、线程是比进程更小的执行单位,它是在一个进程中独立的控制流,即程序内部的控制流。

6、特点:线程不能独立运行,必须依赖与进程,在进程中运行。

7、每个程序至少有一个线程称为主流程。

8、单线程:只有一条线程的进程称为单线程

9、多线程:有不止一个线程的进程称为多线程

二、多线程的优势

1、提高界面的响应速度;

2、充分利用系统资源。

三、多线程的实现

1、继承Thread;

class MyThread extends Thread{

public void run(){

//线程体

}

注意:对于同一个线程类,也可以启动多个线程;

同一个线程不能启动两次。

2、实现Runable接口;

class  MyThread2 implements Runable{

public void run(){}   //重写Runable接口中的run()方法

}

3、使用Timer和TimerTask组合;

实例:

package com.hrxy;

public class ThreadDemo extends Thread{

public static void main(String[] args){

//创建对象

ThreadDemo t=new ThreadDemo();

//启动线程

t.start();

try {

for(int i=0;i<5;i++){

//延长一秒

Thread.sleep(1000);

System.out.println("Main:"+i);

}

catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

public void run(){

for(int i=0;i<5;i++){

try {

Thread.sleep(1000);

System.out.println("Run:"+i);

catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

//Runnable测试类

public class ThreadDemo{

public static void main(String[] args){

//创建对象

Runnable1 t=new Runnable1();

Thread t1=new Thread(t);

//启动线程t1

t1.start();

try {

for(int i=0;i<10;i++){

Thread.sleep(1000);

System.out.println("Main"+i);

}

catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

//使用实现Runnable接口的方式实现多线程

class Runnable1 implements Runnable{

public void run(){

try {

for(int i=0;i<10;i++){

Thread.sleep(1000);

System.out.println("Run"+i);

}

catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

四、线程的生命周期

线程是一个动态执行的过程,它也有一个从产生到死亡的过程,这就是所谓的生命周期。一个线程在它的生命周期内有5种状态(有六种)

1、新建(new):

当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。
例如:Thread  t1=new Thread();

2.就绪(runable):

线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。

例如:t1.start();

3、运行(running):

线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。

4、死亡(dead):

当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。

自然终止:正常运行run()方法后终止

异常终止:调用stop()方法让一个线程终止运行

5、堵塞(blocked)

由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。

正在睡眠:用sleep(long t) 方法可使线程进入睡眠方式。一个睡眠着的线程在指定的时间过去可进入就绪状态。

正在等待:调用wait()方法。(调用notify()方法回到就绪状态)

被另一个线程所阻塞:调用suspend()方法。(调用resume()方法恢复)

实例:电子时钟

package com.hbsi;

import javax.swing.JFrame;

import javax.swing.JLabel;

public class ClockTest extends JFrame{

/**

 * @param args

 */

JLabel clock;

public ClockTest(){

super("我的时钟");

clock=new JLabel("");

clock.setHorizontalAlignment(JLabel.CENTER);

add(clock);

setBounds(200,150,300,200);

setVisible(true);

}

public static void main(String[] args) {

// TODO Auto-generated method stub

}

}

卖票:

package com.hbsi;

public class SaleTicket implements Runnable{

/**

 * @param args

 */

private int ticket=100;

public static void main(String[] args) {

SaleTicket st=new SaleTicket();

Thread t1=new Thread(st);

Thread t2=new Thread(st);

t1.start();

t2.start();

}

@Override

public void run() {

    Object obj=new Object();

while(true){

synchronized (obj) {

if(ticket>0){

try {

Thread.sleep(100);

catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

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

}

}

}

}

}

五、多线程问题及处理

多线编程为程序开发带来了很多的便利,但也带来了一些问题。这些问题是在开发过程中中必须进行处理的。

这些问题的核心是,如果多个线程同时访问一个资源,如变量、文字等,如何保证访问安全?在多线编程中,这种会被多个线程同时访问的资源较临界资源。

(一)为什么需要“线程同步”?

1、线程间共享代码和数据可以节省系统开销,提高程序运行效率,但同时也导致了数据的“访问冲突”问题,如何实现线程间的有机交互、并确保共享资源在某些关键时段只能被一个线程访问,即所谓的“线程同步”(Synchronization)就变得至关重要。

2、Synchronization关键字是一个修饰符,可以修饰方法或代码块。其作用是:对于同一个对象(不是一个类的不同对象),当多个线程都同时调用该方法或代码块,必须依次执行,也就是说,如果两个或两个以上的线程同时执行该代码,如果一个线程已经开始执行该段代码,则另一个线程必须等待这个线程执行完这段代码才能开始执行。

3、synchronized关键字的使用方式有两种:

(1)用在对象前面限制一段代码的执行(同步代码块)
public void push(char c){

sychronized(this){
data[index]=c;
index++
}
}

(2)用在方法声明中,表示整个方法为同步方法:

public  sychronized void show(){}

实例

package com.hbsi;

public class TestSaleTicket {

/**

 * @param args

 */

public static void main(String[] args) {

Tickets t=new Tickets();

TicketThread t1=new TicketThread(t,"张三");

TicketThread t2=new TicketThread(t,"李四");

}

}

class Tickets{

public int ticket;

public Tickets(){

ticket=10;

}

public synchronized void action(String name){

System.out.println(name+"买到了第"+ticket+"号票");

ticket--;

}

}

class TicketThread extends Thread{

Tickets t;

String name;

public TicketThread(Tickets t,String name){

this.t=t;

this.name=name;

start();

}

public void run(){

for(int i=0;i<5;i++){

t.action(name);

try {

Thread.sleep(100);

catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

(二)死锁

两个线程A、B用到同一个对象s(s为共享资源),且线程A在执行中要用到B运行后所创造的条件。在这种前提下A先开始运行,进入同步块后,对象s被锁定,接着线程A因等待B运行结束而进入阻塞状态,于是B开始运行,但因无法访问对象s,线程B也进入阻塞状态,等待s被线程A解锁。最终的结果:两个线程互相等待,都无法运行。

(三)单例

如果一个类始终只能创建一个实例,则这个类被称为单例类。

分两种

1、懒汉式

class Single{

//使用一个变量来缓存创建的实例

   private static Single s=null;

//将构造方法用private修饰,隐藏其构造方法

   private Single(){}

//提供一个静态方法,用于返回Single实例

//该方法可以加入自定义的控制,保证只产生一个Single对象

   public static Single getInstance(){

       if(s==null)

          synchronized(Singel.class){

             if(s==null)

               s=new Single();

         }

         return s;

}

class Single{

   private static Single s=null;

   private Single(){}

   public static synchronized Single getInstance(){

          if(s==null)

              s=new Single();

         return s;

}

Single.getInstance();

2、饿汉式

class Single{

   private static Single s=new Single();

   private Single(){}

   public static Single getInstance(){

         return s;

}

}

六、线程同步通信

    为避免死锁,就应该让线程在进入阻塞状态时尽量释放其锁定的资源,以为其他的线程提供运行的机会,Object类中定义了几个有用的方法:wait()、notify()、notifyAll()。

1、wait():被锁定的对象可以调用wait()方法,这将导致当前线程被阻塞并释放该对象的互斥锁,即解除了wait()方法当前对象的锁定状态,其他的线程就有机会访问该对象。

2、notify():唤醒调用wait()方法后被阻塞的线程。每次运行该方法只能唤醒一个线程。

3、notifyAll():唤醒所有调用wait()方法被阻塞的线程。

实例:

package com.hbsi;

class Res1{

private String name;

private String sex;

private boolean flag;

public synchronized void set(String name,String sex){

if(flag){

try {

this.wait();

catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

this.name=name;

this.sex=sex;

flag=true;

this.notify();

}

public synchronized void out(){

if(!flag){

try {

this.wait();

catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

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

flag=false;

this.notify();

}

}

class Input1 implements Runnable{

private Res1 r;

public Input1(Res1 r){

this.r=r;

}

public void run() {

int i=0;

while(true){

if(i==0){

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

}else{

r.set("lisi","nv");

}

i=(i+1)%2;

}

}

}

class Output1 implements Runnable{

private Res1 r;

public Output1(Res1 r){

this.r=r;

}

public void run() {

while(true){

r.out();

}

}

}

public class ThreadRes {

/**

 * @param args

 */

public static void main(String[] args) {

Res1 r=new Res1();

Input1 in=new Input1(r);

Output1 out=new Output1(r);

Thread t1=new Thread(in);

Thread t2=new Thread(out);

t1.start();

t2.start();

}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值