博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java基础之线程
阅读量:7141 次
发布时间:2019-06-28

本文共 8090 字,大约阅读时间需要 26 分钟。

hot3.png

java基础之线程

一.概述

    1.1  简介

        线程是java的编程中的重中之重,弄清概念是一个程序员的基本功。下面介绍下线程相关的基本概念和实现。

    1.2 进程

        计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位(指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程)

    1.3 线程

        有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元(cpu运行)。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。

        tips:这里形容下,一个应用程序相当于一个仓库,而一个线程相当于一个取货单。有一个管理员(cpu),每一只能取一个商品(计算结果)。管理员不会一次把一个单子的商品取完,而是随机按着一个单子的顺序取一个商品,然后随机按另外一个单子取货。

    1.4 .线程状态 

105200_ISga_2246410.png

        java中的实现:

            a) 新生态:new Thread()对象,这个对象封装了JVM启动一个新线程的方式,当start()后将控制权交给程序计数器,生成新的线程。

            b) 就绪状态“在程序计数器列表中、等待CPU的使用权<start(),notify(),nitify all(),I/O完成>

            d) 运行状态:占用cpu时间,进行逻辑运算。<run(),等待调度器调用>

            e) 阻塞状态:处于不正常的运行和等待中。<jion(),wait(),sleep(),suspend(),I/O请求>

            f) 死亡状态: 运行完成、强行停止。<stop()、destory()>

    1.5 线程总结

        1. 只有run()状态可以直接获取数据的使用权

        2. 线程的研究主要是在运行状态和阻塞状态。 

        3. 线程虽然有优先级,但是JVM并不是100%安装优先级来调用。随机错乱的调用方式

        4. 阻塞的方式:一种是sleep(),整个线程让调度器停止调度。一种是线程在对象锁的等待序列上。

        5. 抽象一个图,便于记忆:线程会在红色部分停止调度,只有在在可执行序列才会被调度。

113319_6P45_2246410.png

二.案例

    2.1 线程名

       每一个线程都会有一个线程名。

          a)主线程名:程序的启动线程接---线程名:main

          b)默认线程名: thread-N(N是数字)

          c)自定义线程名

/** * @see 线程名 *  * @author ssHss * */public class ThreadName implements Runnable {	public static void main(String[] args) {		System.out.println(Thread.currentThread().getName());// main		ThreadName tn = new ThreadName();		Thread tr = new Thread(tn);//线程名:thread-0		Thread tr2 = new Thread(tn, "tr2");//线程名:tr2		tr.start();		tr2.start();	}	@Override	public void run() {		System.out.println(Thread.currentThread().getName());	}}

    2.2 阻止当前线程:下面几种都不会释放对象锁

        a)Thread.yield():让步,建议具有相同优先级的其它线程可以运行了

/** * @see yield:将当前线程从运行态放入到可运行态、将CPU交给线程优先级高的线程 * @author ssHss * */public class ThreadYield implements Runnable {	public static void main(String[] args) {		System.out.println(Thread.currentThread().getName() + " start");		ThreadYield ty = new ThreadYield();		// 线程1		Thread t1 = new Thread(ty, "t--1");		t1.setPriority(8);// 默认的优先级为5		// 线程2		Thread t2 = new Thread(ty, "t--2");		// t1.setPriority(8);		t1.start();		t2.start();		System.out.println(Thread.currentThread().getName() + " end");	}	@Override	public void run() {		for (int i = 0; i < 10; i++) {			System.out.println(Thread.currentThread().getName() + " :获取了 : " + i);			if (i % 3 == 0) {				Thread.yield();			}		}	}}

         b)Thread.sleep(x毫秒):让当前线程阻塞x毫秒。

        c) join():一个线程在其他线程上调用join()方法,其效果将其它线程排在本线程后面。

/** * @see t.JOIN:将当前线程加入到t线程的后面 * */public class ThreadJoin {	public static void main(String[] args) throws InterruptedException {		Sleeper sleepy = new Sleeper("Sleeper", 1500);		Sleeper grumpy = new Sleeper("Grumpy", 1500);		Joiner dopey = new Joiner("Dopey", sleepy);		Joiner doc = new Joiner("Doc", grumpy);		grumpy.interrupt();	}}class Sleeper extends Thread {	private int duration;	public Sleeper(String name, int sleepTime) {		super(name);		duration = sleepTime;		this.start();	}	public void run() {		try {			Thread.sleep(duration);		} catch (Exception e) {			System.out.println(this.getName() + " was interrupted " + this.isInterrupted());		}		System.out.println(this.getName() + " has awakened");	}}class Joiner extends Thread {	private Sleeper sleeper;	public Joiner(String name, Sleeper sleeper) {		super(name);		this.sleeper = sleeper;		this.start();	}	public void run() {		try {			sleeper.join();		} catch (Exception e) {			System.out.println("Ineterrupted");		}		System.out.println(this.getName() + " join completed");	}}

    3.3 Executors:执行器

public class Executor {	/**	 * @see Executor:线程池,管理线程的创建和销毁	 * @param args	 */	public static void main(String[] args) {		//ExecutorService es = Executors.newCachedThreadPool();//创建与所需线程相同数量的线程,回收旧线程时停止新建线程		//ExecutorService es = Executors.newFixedThreadPool(5);//创建固定数量的线程。		ExecutorService es = Executors.newSingleThreadExecutor();//创建单个线程,然后排队执行		for (int i = 0; i < 5; i++) {			es.execute(new TestClass());		}		es.shutdown();	}}class TestClass implements Runnable {	@Override	public void run() {		for (int i = 0; i < 10; i++) {			System.out.println(Thread.currentThread().getName() + " i-->" + i);		}	}}

     3.4 synchronized: 对象锁

        a)每个对象都有一个对象锁,保证线程在操作数据时的,数据一致性。

        c)获取了这个锁,就获取了这个的资源控制权。其它线程只有去对象的对象锁列表(阻塞状态),等待锁释放。在释放锁的时候,会把所有对象锁列表中的线程都移动到可运行列表中。

        b)释放锁的方式:(理解记忆)

            1.自动释放锁(运行完):将对象锁列表中的线程都移动到可运行状态列表,包括自己,然后释放锁。所有线程都是可执行状态,然后抢占锁的使用权。

            2.wait释放锁 :把自己加入到对象锁列表,并释放锁。但是不清理对象锁列表。

           Tips:1.当获取对象锁的时候(synchronzied),会同将锁里面调用的对象一起锁定(当前对象的嵌套、其它对象的调用)。

        c)由于对象锁synchronized使用:

            非静态方法:synchronized(this) 锁的是堆中的地址空间。

            静态方法:synchronized(xxxx.class) 锁的是class 文件存放在永久区的地址空间。一般静态变量最好是放在静态方法中执行,保证安全行。

/** * @see 生存者、消费者模式 * @author ssHss * */public class ThreadSynChron implements Runnable {	Test tc = null;	public static void main(String[] args) {		System.out.println(Thread.currentThread().getName() + " START");		Test test = new Test();		ThreadSynChron tsc = new ThreadSynChron(test);		Thread t1 = new Thread(tsc);		Thread t2 = new Thread(tsc);		t1.start();		t2.start();	}	public ThreadSynChron(Test test) {		this.tc = test;	}	public void A() {		synchronized (this) {			System.out.println(Thread.currentThread().getName() + "  A  ");			this.B();		}	}	public void B() {		synchronized (this) {			System.out.println(Thread.currentThread().getName() + "  B  ");			tc.TestC();		}	}	@Override	public void run() {		synchronized (this) {			System.out.println(Thread.currentThread().getName() + "  run  ");			this.A();		}	}}class Test {	public void TestC() {		synchronized (this) {			System.out.println(Thread.currentThread().getName() + " TestC  ");			this.TestD();		}	}	public void TestD() {		synchronized (this) {			System.out.println(Thread.currentThread().getName() + " TestD  ");		}	}	public void TestE() {		synchronized (this) {			System.out.println(Thread.currentThread().getName() + " TestE  ");		}	}	public void TestF() {		synchronized (this) {			System.out.println(Thread.currentThread().getName() + " TestF  ");		}	}	public void TestG() {		synchronized (this) {			System.out.println(Thread.currentThread().getName() + " TestG  ");		}	}}。

    3.5 线程交互:wait,notify,notify all (只能在对象锁synchronized有用)

        理解记忆:

        a)wait:把自己加入到对象锁列表

        b)nitify:先将对象锁列表中的线程移动到可执行序列,告诉JVM调度器,本对象的使用权即将可用。请做好准备,请在对象锁释放后调用。

package thread;/** * @see 消费这生产者 * @author ssHss * */public class CustomerProduce {	public static void main(String[] args) {		Store st = new Store();		Customer2 ctom = new Customer2(st);		Producer pdc = new Producer(st);		Thread t1 = new Thread(ctom);		Thread t2 = new Thread(pdc);		t1.start();		t2.start();	}}// 消费者class Customer2 implements Runnable {	public Store store;	public Customer2(Store store) {		this.store = store;	}	@Override	public void run() {		synchronized (store) {			System.out.println(Thread.currentThread().getName() + " 开始消费 ");			try {				this.store.customer();			} catch (InterruptedException e) {				e.printStackTrace();			}			System.out.println(Thread.currentThread().getName() + "  消费结束 ");		}	}}// 生成者class Producer implements Runnable {	public Store store;	public Producer(Store store) {		this.store = store;	}	@Override	public void run() {		synchronized (store) {			System.out.println(Thread.currentThread().getName() + " 开始生产 ");			try {				this.store.produce();			} catch (Exception e) {				e.printStackTrace();			}			System.out.println(Thread.currentThread().getName() + "  生存结束 ");		}	}}// 仓库class Store {	private int breadNumber; // 总共	private int afterNumber; // 剩余	// 生成	public void produce() throws InterruptedException {		synchronized (this) {			for (int i = 0; i < 20; i++) {				// 如果还有剩余大于0,则唤醒				if (afterNumber > 0)					this.notify();				// 如果大于5,则等待				if (afterNumber > 5)					this.wait();				breadNumber++;				afterNumber++;				System.out.println(Thread.currentThread().getName() + " 生产了面包: " + breadNumber + " 剩余 " + afterNumber);			}			this.notify();		}	}	// 消费	public void customer() throws InterruptedException {		synchronized (this) {			for (int i = 0; i < 15; i++) {				if (afterNumber <= 2)//					this.notify();				// 如果还有剩余==0,则等待				if (afterNumber == 0)					this.wait();				afterNumber--;				System.out.println(Thread.currentThread().getName() + " 消费了面包: " + breadNumber + " 剩余 " + afterNumber);			}			this.notify();		}	}}

        最开始执行状态:

150243_77Tq_2246410.png

        调用notify():

152426_jAui_2246410.png

        调用:wait()

152440_ghcL_2246410.png

        执行结果:

152453_5cS7_2246410.png

转载于:https://my.oschina.net/u/2246410/blog/552316

你可能感兴趣的文章
在AndroidStudio中如何显示出依赖库的本地存储路径
查看>>
面向对象主要有四大特性
查看>>
Spring Cloud:使用Ribbon实现负载均衡详解(上)
查看>>
多线程 NSLock 数据加锁
查看>>
core java 详解附练习题
查看>>
大云之下-----新技术下的网络变革
查看>>
字符画工具
查看>>
vSphere Network Teaming Options
查看>>
Install and Configure OpenStack Identity Service (Keystone) for Ubuntu 14.04
查看>>
我的友情链接
查看>>
Chapter 13 Strings and Regular Expressions
查看>>
动态调用webservice
查看>>
Hadoop的问题
查看>>
vsftpd 500 OOPS: cannot change directory
查看>>
《linux下sudo的深入分析》
查看>>
jquery怎样获取多个复选框的值
查看>>
Tomcat安全配置与性能优化
查看>>
Python学习笔记-字典使用
查看>>
光纤模块
查看>>
配置Tomcat输出log文件
查看>>