Java多线程机制详解
2015-10-16 22:26
429 查看
一.创建线程的两种方式
1.继承Thread
class MyThread extends Thread{ private static int ticket = 10; private String name; public MyThread(String name){ this.name =name; } public void run(){ while(this.ticket>0){ System.out.println(this.name+"卖票---->"+(this.ticket--)); } } }
2.实现Runnable接口
class MyThread implements Runnable{ private int ticket =10; private String name; public void run(){ while(this.ticket>0){ System.out.println(this.name+"卖票---->"+(this.ticket--)); } } }
二.线程的5种状态
1.新生状态(创建状态)。在生成线程对象,但是没有调用对象的start()方法时,该线程处于创建状态
2.就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,此时线程具有CPU的执行资格,但是没有CPU的执行权。
3.运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,开始运行run函数当中的代码,此时线程就进入运行状态,处于运行状态的线程既有CPU的执行资格,又有CPU的执行权。
4.阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend,wait等方法都可以导致线程阻塞。此时线程既没有CPU的执行资格,也没有CPU的执行权。
5.死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪转态。
sleep()与wait()的区别?
如果当前线程进入了同步锁,调用sleep()方法并不会释放锁,其他被同步锁挡住了的线程也无法得到执行,在sleep()指定的时间过后,线程会自动回到就绪状态等待CPU的执行;而wait()方法会释放同步锁,以便其他正在等待此锁的线程可以得到同步锁并运行,只用其他线程调用了notify()或notifyAll()方法,线程才会回到就绪状态。但是notify()方法并不释放同步锁,只是告诉调用过wait()方法的线程去参与同步锁的竞争,但不是马上得到锁,因为锁在别人手里,别人还没释放。
三.线程的同步
同步与异步有何不同,在什么情况下使用它们?如果数据在多个线程之间共享并且操作共享数据的代码不止一条时,就需要对共享数据进行同步处理,即某一个线程在操作共享数据时,其他线程无法操作,只到该线程释放共享数据。当应用程序调用一个需要花费很长时间来执行的方法,并且不需要等待返回结果时,就采取异步操作,例如:下载资源。
同步的好处和弊端?
好处:解决了线程的安全性问题
弊端:降低了效率,因为同步外的线程都要判断同步锁
1.同步代码块
思路:将操作共享数据的多条代码封装起来package com.ghs.sort; public class Demo{ public static void main(String[] args){ Ticket t = new Ticket(); Thread t1 = new Thread(t); Thread t2 = new Thread(t); Thread t3 = new Thread(t); Thread t4 = new Thread(t); t1.start(); t2.start(); t3.start(); t4.start(); } } class Ticket implements Runnable{ int num=100; //所有的线程共用一个num对象 Object obj = new Object(); public void run(){ while(true){ synchronized(obj){ if(num>0){ System.out.println(Thread.currentThread().getName()+"......sale......"+num--); } } } } }
同步锁就相当于一个标志位,初始值为1,有线程进去了,值就变为0,只有当同步锁为1的时候,其他线程才能进去。
2.同步函数
public class Demo { public static void main(String[] args) { BankRun br = new BankRun(); Thread t1 = new Thread(br); Thread t2 = new Thread(br); t1.start(); t2.start(); } } class BankRun implements Runnable { Bank b = new Bank(); public void run() { b.add(100); } } class Bank { private int sum; //模拟存钱的过程 public synchronized void add(int num) { //此处存在安全问题,采用同步函数来解决 sum = sum + num; System.out.println(Thread.currentThread() + "......Total=" + sum); } }
注意:
1. 同步函数的锁是this
2. 静态同步函数的锁是Class对象而不是this,因为静态函数没有所属的对象
当一个线程进入一个对象的synchronized方法后,其他线程是否可以进入此对象的其他方法?
1. 其他方法前如果不是synchronized方法,则能进入。
2. 如果这个方法内部调用了wait,则能进入其他的synchronized方法。
3. 其他方法如果都加了synchronized,并且内部没有调用wait,则不能进入。
3. 如果其他方法是static,它的同步锁是当前类的字节码,与非静态方法不能同步,所以能进入。
相关文章推荐
- java-模拟tomcat服务器
- Python3写爬虫(四)多线程实现数据爬取
- 使用 Syncthing 在多个设备间同步文件
- C#实现多线程的同步方法实例分析
- 浅谈chuck-lua中的多线程
- Lua中实现sleep函数功能的4种方法
- 科学知识:同步、异步、阻塞和非阻塞区别
- 同步文件备份工具 Super Flexible File Synchronizer Pro v4
- 探讨Ajax中同步与异步之间的区别
- MySQL Sleep连接过多问题解决方法
- C#简单多线程同步和优先权用法实例
- C#多线程学习之(四)使用线程池进行多线程的自动管理
- C#多线程编程中的锁系统(三)
- C#线程同步的三类情景分析
- C#多线程学习之(六)互斥对象用法实例
- 基于一个应用程序多线程误用的分析详解
- C#多线程学习之(三)生产者和消费者用法分析
- C#多线程学习之(一)多线程的相关概念分析
- C#多线程之Thread中Thread.IsAlive属性用法分析
- rsync命令使用总结