JAVA学习笔记(初级)--多线程

1 线程

多任务:操作系统完成多任务是多线程存在的原因。

线程:进程中单一顺序的执行流。多个线程共享相同地址空间并构成进程。

注意:这里可以参考操作系统一起学习,进程与线程的比较,在面试或者笔试时也经常会出。

多线程:一个程序同时具备完成多个任务的能力。多线程指一个程序包中含有多个执行流,是实现并发的有效手段。

2 线程的状态及转换

  • 新建:new Thread()之后的线程状态
  • 就绪:在新建之后调用线程的start()方法之后启动线程之后的状态
  • 运行:再就绪之后调用run()方法让线程出于运行状态
  • 阻塞:处于运行状态的线程调用sleep()/wait(),suspend()/yield()等方法之后线程处于阻塞状态
  •  死亡:run()方法运行结束

 注意:线程放弃CPU的占有权有一下几种方式:

  • 优先级较低时遇到优先级较高的线程
  • 线程调用yield()/sleep()
  • 线程调用suspend()挂起
  • 线程调用wait()等待
  • 输入输出流发生线程阻塞

 重点在于掌握线程的就绪,运行河阻塞三种状态的转换,转换的实现(及实现状态转换的方法)

线程优先级:Thread.getPriority()可以获取线程的优先级,setProirity()可以设置线程优先级,默认为5.

3 线程的实现

  • 继承Thread类
  • 实现Runnable接口

 继承Thread类创建一个线程类

public class CountingThread extends Thread{
	public void run(){
		System.out.println();
		System.out.println("子线程"+this+"开始");
		for(int i=0;i<8;i++){
			System.out.println(this.getName()+".i"+(i+1)+"/t");
		}
		System.out.println();
		System.out.println("子线程"+this+"结束");
	}
    
}

 在测试类中新建三个线程对象

public class ThreadTest {
	public void mian(String[] args){
		System.out.println("主线程开始");
		CountingThread th1=new CountingThread();
		th1.start();
		CountingThread th2=new CountingThread();
		th2.start();
		CountingThread th3=new CountingThread();
		th3.start();
		System.out.println("主线程结束");
	}
}

这里有点也许是别人不会说到的,就是在控制台里编和运行可能都直接用javac,java指令即可,但是我用的是myeclipse,当写好线程类和测试类的时候,要进行调试和运行,却不知道应该如何操作,现在问了一些人也没找到答案,先放着,后面专门写一篇来介绍这个问题吧,不然妨碍进度。

以上程序每次运行的结果都不一样,而且运行的时候线程的切换也是无序的,体现线程的不可控性。

  • 线程的暂停与恢复

暂停:sleep(),yield(),wait()比较:

sleep(st),线程在休眠st毫秒之后被唤醒;

yield(),线程让出CPU,不允许优先级更低的线程获得CPU;

wait(),线程进入等待状态,必须由notify()或notifyAll()唤醒;

线程使用的一些技巧

  • 编写一个类继承Thread类
  • 增加一个running变量并初始化为false
  • 覆盖start()方法,先将running设置为true,然后调用super.start()
  • 提供一个halt()方法将running设置为false
  • 如下写run()方法
    public void run(){
       while(running){
         ...
        }
    }

    这样在一个线程调用halt方法的时候便可以结束线程,而不用调用stop()(已经建议不再使用的方法)。

 课本上还实现了一个继承Thread类实现多线程的例子,一个笼子里有多只鸟的例子,不再介绍,可以认真的研读书本上的代码,学习框架和细节技巧。

同样书上也实现了一个实现Runnable接口实现多线程的例子,重点在于重写Runnable的run()方法,代码不多,但框架很完整,值得好好研究。

4 线程的同步

书本上给出了两个个在不做同步处理的情况下的例子,表现了非同步状态下数据如何崩溃的,这点是我们学习多线程必须知道的,但是研究数据崩溃不是我们的主要目的,我们的目的是学习如何写出不会造成数据错误和崩溃的多线程应用。即重点是学习如何做线程的同步。

线程同步的方法:

  • synchronized 方法:即用synchronized修饰方法,则此方法在任何时候都只允许一个线程来调用,其他线程必须等待,直到这个线程将该方法执行结束。同样是只能控制任何时候只能允许一个线程执行,但在多线程时不能控制是哪个线程获得调用权。
  • 管程(Monitor),也叫互斥锁。管程是一个能够拒绝访问和允许访问的对象。每个拥有synchronized方法的对象拥有唯一的一个互斥锁,放过来说,只有获得互斥锁的对象才能去调用synchronized方法。实现机制:一个调用管程入口的线程发现资源已经被分配时则调用wait()方法进入等待队列排队,而拥有资源的线程如果想放弃资源的使用权即释放资源需要调用notify()或者notifyAll()方法通知某个正在等待的线程或者是通知 所用正在等待的线程。

 以上即使实现同步的方法,但是,这种同步很有可能会产生死锁,即导致所有的线程都处于等待状态,浪费CPU资源。所以在程序设计的时候要考虑是否会导致死锁的情况,即慎用wait()和notify().

课本上给出了发生死锁的例子,同样也给出了解决方法。不再细说,好好看代码和说明。

转载于:https://my.oschina.net/jfchenhust/blog/775991

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值