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

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

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

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

public class Threadtest implements  Runnable
{
@Override
void run()
{
//写你需要这个进程进行的操作
}
}

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

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

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

新生(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、public/private/protected 函数返回类型 synchronized 函数名(形参)
{
//函数内容
}
例如:
public void synchronized FuncName()
{
//do something
} 2、public/private/protected 函数返回类型 函数名(形参)
{
synchronized(this)

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

//其他操作
}

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

public class ThreadTest1
{
private int j;
public static void main(String args[]){
ThreadTest1 tt=newThreadTest1();
Inc inc=tt.new Inc();
Dec dec=tt.new Dec();
for(inti=0;i<2;i++){
Thread t=newThread(inc);
t.start();
t=new Thread(dec);
t.start();
}
}
private synchronized void inc(){
j++;
System.out.println(Thread.currentThread().getName()+"-inc:"+j);
}
private synchronized void dec(){
j--;
System.out.println(Thread.currentThread().getName()+"-dec:"+j);
}
class Inc implements Runnable{
public void run(){
for(inti=0;i<100;i++){
inc();
}
}
}
class Dec implements Runnable{
public void run(){
for(inti=0;i<100;i++){
dec();
}
}
}
}

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

import java.util.concurrent.locks.*;
public class LockTest
{
Lock lock = new ReentrantLock();// 锁
//定义一个公共资源
private int val = 0;
//再定义两个私有类,两个类都应用Runnable接口:
private class IncClass implements Runnable()
{
//重写run
void run()
{
lock.lock(); //锁定
try{
//对竞争资源的操作
val++;
System.out.println("现在value的值是"+val);
}catch(Exception e){
}
lock.unlock(); //释放锁
}
}
private class DecClass implements Runnable()
{
//重写run
void run()
{
lock.lock();
try{
val--;
System.out.println("现在value的值是"+val);
}catch(Exception e){
}
lock.unlock();
}
}
//主方法
public static void main(String[] args) throws Exception
{
LockTest lt = new LockTest();
for(int i = 0 ; i< 10 ; i++)
{
new Thread(lt.new IncClass()).start();
new Thread(lt.new DecClass()).start();
}
}
}

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

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest {
/**
* @paramargs
*/
private int j;
private Lock lock =new ReentrantLock();
public static void main(String[] args) {
// TODO Auto-generated method stub
LockTest tt = new LockTest();
for(int i=0;i<2;i++)
{
new Thread(tt.new Adder()).start();
new Thread(tt.new Subtractor()).start();
}
} //两个内部类,作为数据成员的形式出现
private class Subtractor implements Runnable {
@Override
public void run() {
// TODO Auto-generated methodstub
while(true)
{
/*synchronized (ThreadTest.this) {
System.out.println("j--="+ j--);
//这里抛异常了,锁能释放吗?
}*/
lock.lock();
try
{
System.out.println("j--="+ j--);
}finally
{
lock.unlock();
}
}
}
} private class Adder implements Runnable
{
@Override
public void run() {
// TODO Auto-generated methodstub
while(true)
{
/*synchronized (ThreadTest.this) {
System.out.println("j++="+ j++);
}*/
lock.lock();
try
{
System.out.println("j++="+ j++);
}finally
{
lock.unlock();
}
}
}
}
}

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

 六、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. git登陆迁移 SourceTree 不能自动识别

    公司切换了迁移了git登陆,具体是什么 我也不是很清楚,结果就是,周一上班 好多小伙伴的git 用不了了,办公室里自然是哀嚎一片, 运维小伙伴给出的解决方案是:改个密码就好啦: 于是照做 结果Sour ...

  2. Android无线测试之—UiAutomator UiObject API介绍五

    获取对象属性与属性的判断 1.获取对象属性相关API 返回值 API 说明 Rect getBounds() 获取对象矩形坐标,矩形左上角坐标与右下角坐标 int getChildCount() 获得 ...

  3. JS循环语句的理解

    循环语句就是让程序重复性去做某些工作 最常见的就是for循环 那它的写法都有哪些呢? 1.必须要有初始值 2.要有条件判断 3.状态的改变 4.循环体 一定要控制循环多少次结束,否则就变成了死循环,消 ...

  4. hdu3729(二分图)

    比赛的时候没有想到二分图,一直在想dp和贪心. 原因是因为看到数据是100000所以直接就没有往二分图匹配上想. 现在想想. 因为二分图两边的太不对称了,60 和100000 , 如果用匈牙利算法考虑 ...

  5. 【IDEA】安装Jrebel插件:JRebel6.4.3+破解补丁

    Jrebel 通过社交分享得到的激活码不能用了.在网上找了一波,发现通过反向代理破解最好,但激活过程中报错 Check your network connection and/or VPN setti ...

  6. 火狐老是弹出下载openh264-win32.zip怎么取消

    OpenH264插件是WebRTC需要调用的一个解码器,从33版本开始内置,默认会自动下载安装和更新,出现这种情况的原因是迅雷或其他下载软件监视浏览器进程,导致火狐无法自动下载响应插件到配置文档中.解 ...

  7. jquery练习题

    1.自定义登录校验 用户输入用户名和密码 输入的用户名和密码不能为空 如果用户输入的用户名或者密码为空,你就提示它用户名不能为空或者密码不能为空. 知识点:文本操作相关 <!DOCTYPE ht ...

  8. Powershell数据处理

    1.导出csv文档 Export-Csv D:\ps\xxx.csv -Encoding UTF8 -NoTypeInformation 2.发送mail $from="frommailad ...

  9. Character Sets, Collation, Unicode :: utf8_unicode_ci vs utf8_general_ci

    w Hi, You can check and compare sort orders provided by these two collations here: http://www.collat ...

  10. 贪玩ML系列之CIFAR-10调参

    调参方法:网格调参 tf.layers.conv2d()中的padding参数 取值“same”,表示当filter移出边界时,给空位补0继续计算.该方法能够更多的保留图像边缘信息.当图片较小(如CI ...