本篇笔记记录一些在Java多线程编程中常见的关键字,比较简单和基础的就不写太详细了。

一、Thread类(其实也是应用了Runnable接口)和Runnable接口(只有一个run方法,应用该类必须重写run方法)

一般我们定义一个线程类,可以继承Thread类或者应用Runnable接口,不管是继承哪个,都要重写run方法。

比如我们定义一个线程类:

  1. public class Threadtest implements Runnable
  2. {
  3. @Override
  4. void run()
  5. {
  6. //写你需要这个进程进行的操作
  7. }
  8. }

然后在主方法里面生成线程对象并调用start()方法运行:

  1. public static void main(String args[]){
  2. new Thread(new Threadtest()).start();
  3. }

一般来说线程有以下几种状态:

新生(New):这个状态下我们通过new关键字生成了新的线程Thread对象,为它分配了内存空间,但是这个线程并不是存活状态;

就绪(Runnable):线程对象调用start()方法,线程进入runnable状态,等待分配CPU资源。这个时候线程是存活的;

运行(Running):获取CPU资源后,线程开始进行,run()方法被执行,直到线程结束,或者因为资源耗尽等原因被中断或挂起;

阻塞(Blocked):线程调用join()、sleep()和wait()等方法而暂处阻塞状态;

死亡(Dead):线程结束,或者因为异常而被迫中断或异常退出,生命周期结束。

三、sleep方法和wait方法
3.1、sleep方法(只释放CPU,不释放锁),比如一个变量i,好几个线程都要用到,线程A调用sleep方法只释放了CPU,但是A没有释放i的锁,而那几个线程又刚好需要i达到一定条件才能继续运行,所以线程A就算释放了CPU也没用。

 3.2、wait方法(释放CPU和锁),比如有两个进程,进程A调用wait方法之后,进程释放CPU和锁,要等待线程B调用notify方法或notifyAll方法来通知A,你可以来抢夺资源了,但是A不一定就能抢得到。

四、synchronized同步标志

使用场合:比如这里有个资源j,好几个线程都要用到,我们把它叫做竞争资源(竞态条件),对这样的共享资源我们就要进行同步操作,以免一个线程对这个变量的操作被另一个线程覆盖了。通常有两种使用方法:

  1. 1public/private/protected 函数返回类型 synchronized 函数名(形参)
  2. {
  3. //函数内容
  4. }
  5. 例如:
  6. public void synchronized FuncName()
  7. {
  8. //do something
  9. }
  10.  
  11. 2public/private/protected 函数返回类型 函数名(形参)
  12. {
  13. synchronizedthis

  14. //需要进行同步操作的函数内容

  15. //其他操作
  16. }

下面来个经典的面试题:给个变量j给你,叫你写个两个函数(线程)一个对它进行累加操作,一个对它进行递减操作。然后在主函数里产生四个线程,两个进行累加,两个进行递减。

  1. public class ThreadTest1
  2. {
  3. private int j;
  4. public static void main(String args[]){
  5. ThreadTest1 tt=newThreadTest1();
  6. Inc inc=tt.new Inc();
  7. Dec dec=tt.new Dec();
  8. for(inti=0;i<2;i++){
  9. Thread t=newThread(inc);
  10. t.start();
  11. t=new Thread(dec);
  12. t.start();
  13. }
  14. }
  15. private synchronized void inc(){
  16. j++;
  17. System.out.println(Thread.currentThread().getName()+"-inc:"+j);
  18. }
  19. private synchronized void dec(){
  20. j--;
  21. System.out.println(Thread.currentThread().getName()+"-dec:"+j);
  22. }
  23. class Inc implements Runnable{
  24. public void run(){
  25. for(inti=0;i<100;i++){
  26. inc();
  27. }
  28. }
  29. }
  30. class Dec implements Runnable{
  31. public void run(){
  32. for(inti=0;i<100;i++){
  33. dec();
  34. }
  35. }
  36. }
  37. }

五、Lock方法和unLock方法
jdk5.0版本及之前只有synchronized,后来就有了Lock方法,synchronized能做的事情Lock方法都能做,而且锁的获取和释放更加明确,因为编程人员需要明确给出释放锁的时机,是更严谨的机制。
这个的用法也比较简单,我们先给出下面的类定义,方便解释:

  1. import java.util.concurrent.locks.*;
  2. public class LockTest
  3. {
  4. Lock lock = new ReentrantLock();// 锁
  5. //定义一个公共资源
  6. private int val = 0;
  7. //再定义两个私有类,两个类都应用Runnable接口:
  8. private class IncClass implements Runnable()
  9. {
  10. //重写run
  11. void run()
  12. {
  13. lock.lock(); //锁定
  14. try{
  15. //对竞争资源的操作
  16. val++;
  17. System.out.println("现在value的值是"+val);
  18. }catch(Exception e){
  19. }
  20. lock.unlock(); //释放锁
  21. }
  22. }
  23. private class DecClass implements Runnable()
  24. {
  25. //重写run
  26. void run()
  27. {
  28. lock.lock();
  29. try{
  30. val--;
  31. System.out.println("现在value的值是"+val);
  32. }catch(Exception e){
  33. }
  34. lock.unlock();
  35. }
  36. }
  37. //主方法
  38. public static void main(String[] args) throws Exception
  39. {
  40. LockTest lt = new LockTest();
  41. for(int i = 0 ; i< 10 ; i++)
  42. {
  43. new Thread(lt.new IncClass()).start();
  44. new Thread(lt.new DecClass()).start();
  45. }
  46. }
  47. }

上面的代码没编译运行过,因为直接在文本文档里面敲的,不过也就是那个意思。你要对一个竞态资源进行写操作的时候,先获得锁,这样其他进程没办法对它进行访问,操作完成之后释放锁。
为了有个确定能运行的例子,去抄了别人写的可以运行的测试代码过来:

  1. import java.util.concurrent.locks.Lock;
  2. import java.util.concurrent.locks.ReentrantLock;
  3. public class LockTest {
  4. /**
  5. * @paramargs
  6. */
  7. private int j;
  8. private Lock lock =new ReentrantLock();
  9. public static void main(String[] args) {
  10. // TODO Auto-generated method stub
  11. LockTest tt = new LockTest();
  12. for(int i=0;i<2;i++)
  13. {
  14. new Thread(tt.new Adder()).start();
  15. new Thread(tt.new Subtractor()).start();
  16. }
  17. }
  18.  
  19. //两个内部类,作为数据成员的形式出现
  20. private class Subtractor implements Runnable
  21.  
  22. {
  23. @Override
  24. public void run() {
  25. // TODO Auto-generated methodstub
  26. while(true)
  27. {
  28. /*synchronized (ThreadTest.this) {
  29. System.out.println("j--="+ j--);
  30. //这里抛异常了,锁能释放吗?
  31. }*/
  32. lock.lock();
  33. try
  34. {
  35. System.out.println("j--="+ j--);
  36. }finally
  37. {
  38. lock.unlock();
  39. }
  40. }
  41. }
  42. }
  43.  
  44. private class Adder implements Runnable
  45. {
  46. @Override
  47. public void run() {
  48. // TODO Auto-generated methodstub
  49. while(true)
  50. {
  51. /*synchronized (ThreadTest.this) {
  52. System.out.println("j++="+ j++);
  53. }*/
  54. lock.lock();
  55. try
  56. {
  57. System.out.println("j++="+ j++);
  58. }finally
  59. {
  60. lock.unlock();
  61. }
  62. }
  63. }
  64. }
  65. }

如果是多个线程读取,一个线程进行写的话,只需要给进行写操作的进程锁即可,读取操作那些线程一般是不需要锁的。

 六、join方法

因为join方法使用方法比较神奇,我看了有篇博文讲得很好,不过看了几遍还是比较晕乎,主要是因为运用得不多,所以理解不深刻。其实学习还是要用任务驱动的方式最高效,这种纯学但是没有运用条件和环境的学习是没什么效果的。

给出join方法的帮助文档:

它的字面意思是:等当前调用join方法的进程在限定时间内死亡,如果限定时间为0,则一直等待。它的实现是通过一个条件为“this.alive”的“this.wait”循环操作进行的,即是:只要判断这个进程存活,则进行“this.wait”循环,等这个进程终结的时候通过this.notifyAll来通知其他进程争夺资源。
最后推荐一篇写得还不错的博文,虽然排版有点惨不忍睹,不过内容是不错的:

http://java.chinaitlab.com/base/828720.html

Java多线程基础知识总结笔记的更多相关文章

  1. Java 多线程——基础知识

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  2. Java多线程基础知识笔记(持续更新)

    多线程基础知识笔记 一.线程 1.基本概念 程序(program):是为完成特定任务.用某种语言编写的一组指令的集合.即指一段静态的代码,静态对象. 进程(process):是程序的一次执行过程,或是 ...

  3. Java多线程基础知识总结

    2016-07-18 15:40:51 Java 多线程基础 1. 线程和进程 1.1 进程的概念 进程是表示资源分配的基本单位,又是调度运行的基本单位.例如,用户运行自己的程序,系统就创建一个进程, ...

  4. Java多线程基础知识篇

    这篇是Java多线程基本用法的一个总结. 本篇文章会从一下几个方面来说明Java多线程的基本用法: 如何使用多线程 如何得到多线程的一些信息 如何停止线程 如何暂停线程 线程的一些其他用法 所有的代码 ...

  5. JAVA多线程基础知识(一)

    一. 基础知识 要了解多线程首先要知道一些必要的概念,如进程,线程等等.开发多线程的程序有利于充分的利用系统资源(CPU资源),使你的程序执行的更快,响应更及时. 1. 进程,一般是指程序或者任务的执 ...

  6. Java多线程基础知识例子

    一.管理 1.创建线程 Thread public class Main { public static void main(String[] args) { MyThread myThread = ...

  7. Java多线程基础知识(二)

    一. Java线程具有6种状态  NEW 初始状态,线程被创建,但是还没有调用start方法. RUNNABLE 运行状态,java线程将操作系统中的就绪和运行两种状态笼统的称作进行中. BLOCKE ...

  8. Java多线程-基础知识

    一. 进程是执行中的程序,程序是静态的(我们写完以后不运行就一直放在那里),进程是执行中的程序,是动态概念的.一个进程可以有多个线程. 二. 多线程包含两个或两个以上并发运行的部分,把程序中每个这样并 ...

  9. Java多线程基础知识(五)

    一. Java中的13个原子操作类 在Jdk1.5中,这个包中的原子操作类提供了一种用法简单,性能高效,线程安全的更新一个变量的方式. 1. 原子更新基本类型类 AtomicBoolean : 原子更 ...

随机推荐

  1. 修改一些IntelliJ IDEA 11的设置,使Eclipse的使用者更容易上手(转)

    用惯了Eclipse,再来使用IntelliJ IDEA真是很难适应. 设置1:字体 修改IDE的字体:设置-Appearance-Look and Feel-OverRide设置你想要的字体.我设置 ...

  2. 使用python封装get+post请求

    思路: 将平时用的多的get和post请求封装,提高代码重用率. 其中Session类可以通过实例化,保存cookie信息,可以在程序结束前多次通过保存的cookie信息保持登录状态的访问. 那么为什 ...

  3. 我如何让echarts实现了分组(原创插件echarts.group代码分享)

    前言 echarts是百度出品的一款很棒的前端图表控件,被评为“百度少有的良心产品”.可以实现散点图.折线图.柱状图.地图.饼图.雷达图.K线图等等几十种常用.不常用的图表,效果酷炫. 示例地址:ht ...

  4. xmpp muc 群聊协议 1

    翻译来自 :http://wiki.jabbercn.org/index.php?title=XEP-0045&variant=zh-cn#.E6.9C.AF.E8.AF.AD 通用术语 Af ...

  5. 通过脚本同时运行几个spider

    # 通过脚本同时运行几个spider目录结构: 1.在命令行能通过的情况下创建两个spider如TestSpiderTest2Spider 2.在items.py的同级目录创建run.py文件,有三种 ...

  6. delphi 事件记录

    delphi常用事件 序号 事件 描述 1. OnActive 焦点称到窗体或控件时发生 2. OnClick 鼠标单击事件 3. OnDbClick 鼠标双击事件 4. OnClose和OnClos ...

  7. 第二课——解析mysqldump命令和mysqlbinlog命令+innodb和Myisam存储引擎简介

    环境说明 mysql版本:Percona-Server-5.6.30 IP:10.7.15.167 端口:3306 安装目录:/httx/run/mysql 数据目录:/httx/run/mysql/ ...

  8. js function,prototype,sub.

    Ojbect 和Function 与普通函数和实例对象 1.实例对象的proto 指向构造函数的原型对象 2.实例对象的proto 指向Ojbect的原型 3.所有函数的proto 都指向Functi ...

  9. Java 语言基础之数组应用

    什么时候使用数组呢? 如果数据出现了对应关系, 而且对应关系的一方是有序的数字编号, 并作为角标使用. 这时,就必须要想到数组的使用. 也就是将这些数据存储到数组中, 根据运算的结果作为角标, 直接去 ...

  10. 转!!mysql 查询条件不区分大小写问题

    做用户登录模块时,输入用户名(大/小写)和密码 ,mysql都能查出来.-- mysql查询不区分大小写. 转自 http://blog.csdn.net/qishuo_java/article/de ...