黑马程序员技术交流社区
标题: 【黑马程序员合肥】java基础之线程 [打印本页]
作者: 项老师 时间: 2017-8-29 14:31
标题: 【黑马程序员合肥】java基础之线程
【黑马程序员合肥】java基础之线程
摘要: Java基础-线程这些是黑马程序员java基础的一个很核心的内容。今天主要给大家简单讲解一下Java 基础-线程,以后会慢慢讲解黑马程序员的课程内容!
一.概述
1.1 简介
线程是java的编程中的重中之重,弄清概念是一个程序员的基本功。下面介绍下线程相关的基本概念和实现。
1.2 进程
计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位(指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程)
1.3 线程
有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元(cpu运行)。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。
tips:这里形容下,一个应用程序相当于一个仓库,而一个线程相当于一个取货单。有一个管理员(cpu),每一只能取一个商品(计算结果)。管理员不会一次把一个单子的商品取完,而是随机按着一个单子的顺序取一个商品,然后随机按另外一个单子取货。
1.4 .线程状态
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. 抽象一个图,便于记忆:线程会在红色部分停止调度,只有在在可执行序列才会被调度。
二.案例
2.1 线程名
每一个线程都会有一个线程名。
a)主线程名:程序的启动线程接---线程名:main
b)默认线程名: thread-N(N是数字)
c)自定义线程名
[AppleScript] 纯文本查看 复制代码
/**
* @author 传智播客
*/
/**
* @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():让步,建议具有相同优先级的其它线程可以运行了。
[AppleScript] 纯文本查看 复制代码
/**
* @将当前线程从运行态放入到可运行态、将CPU交给线程优先级高的线程
* @author 传智播客
*
*/
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()方法,其效果将其它线程排在本线程后面。
[AppleScript] 纯文本查看 复制代码
/**
* @author 传智播客
*/
/**
* @ 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");
}
}
2.3 Executors:执行器
[AppleScript] 纯文本查看 复制代码
/**
* @author 传智播客
*/
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);
}
}
}
2.4 synchronized: 对象锁
a)每个对象都有一个对象锁,保证线程在操作数据时的,数据一致性。
c)获取了这个锁,就获取了这个的资源控制权。其它线程只有去对象的对象锁列表(阻塞状态),等待锁释放。在释放锁的时候,会把所有对象锁列表中的线程都移动到可运行列表中。
b)释放锁的方式:(理解记忆)
1.自动释放锁(运行完):将对象锁列表中的线程都移动到可运行状态列表,包括自己,然后释放锁。所有线程都是可执行状态,然后抢占锁的使用权。
2.wait释放锁 :把自己加入到对象锁列表,并释放锁。但是不清理对象锁列表。
Tips:1.当获取对象锁的时候(synchronzied),会同将锁里面调用的对象一起锁定(当前对象的嵌套、其它对象的调用)。
c)由于对象锁synchronized使用:
非静态方法:synchronized(this) 锁的是堆中的地址空间。
静态方法:synchronized(xxxx.class) 锁的是class 文件存放在永久区的地址空间。一般静态变量最好是放在静态方法中执行,保证安全行。
[AppleScript] 纯文本查看 复制代码
/**
* @生存者、消费者模式
* @author 传智播客
*
*/
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 ");
}
}
}
2.5 线程交互:wait,notify,notify all (只能在对象锁synchronized有用)
理解记忆:
a)wait:把自己加入到对象锁列表
b)nitify:先将对象锁列表中的线程移动到可执行序列,告诉JVM调度器,本对象的使用权即将可用。请做好准备,请在对象锁释放后调用。
[AppleScript] 纯文本查看 复制代码
package thread;
/**
* @author 传智播客
*/
/**
* @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();
}
}
}
最开始执行状态:
调用notify():
调用:wait()
执行结果:
其实在学习java过程中基础还是比较容易,如果大家想学习java基础的知识,欢迎大家可以去传智播客官网去了解java基础知识!
作者: hguilin 时间: 2017-9-20 11:58
我的天,巨生动,棒棒哒
作者: Lase 时间: 2017-10-24 19:52
6666666666
作者: 播妞 时间: 2017-10-25 07:16
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |