java并发编程基础---Sky
1.线程及启动和终止
1.1 线程 -进程/优先级
操作系统调度的最小单元是线程,线程是轻量级进程。
线程优先级由setPriority(int)方法来设置,默认优先级是5,等级1~10.等级越高分的时间片越多。
1.2 线程的状态
new 初始化 》》Runable 运行》》Blocked阻塞 》》Wating等待》》 time_Wating超时等待》》 temerinated终止状态。
1.3 Daemon辅助线程
主线程终止后,辅助线程也就结束。thread.setDaemon(true)设置在线程开始之前。
1.4 过期suspend() , resume(), stop()为啥不建议使用?
suspend()调用后太霸道,不释放占有资源,而是抱着占有资源去睡觉,这样容易死锁。站着茅坑不拉屎。
resume()、stop()不保证线程资源正常释放,那要你们何用?
安全的终止线程:有中断操作,和自定义cancel()方法。
package Thread; import java.util.concurrent.TimeUnit; /**
* Created by Sky on 2016/9/22.
* @author xiaoyongyong
*/
public class Shutdown {
public static void main(String[] args) throws InterruptedException {
Runner one = new Runner();
Thread countThread = new Thread(one,"CountThread");
countThread.start();
TimeUnit.SECONDS.sleep(1);
countThread.interrupt(); Runner two = new Runner();
countThread = new Thread(two,"CountThread");
countThread.start();
TimeUnit.SECONDS.sleep(1);
two.cancle();
} private static class Runner implements Runnable{
private long i;
private volatile boolean on =true;
@Override
public void run() {
while (on && !Thread.currentThread().isInterrupted()){
i++;
}
System.out.println("Count i ="+ i);
}
public void cancle(){
on = false;
}
}
}
2. 线程之间通信
2.1 volatile 和 synchronized 关键字。
volatile:它能保证所有线程对变量访问的可见性,即某线程对定义变量的修改,其他线程可见。谨慎使用,过多使用会降低程序运行效率。
syncchronized:保证只有一个线程能对其定义的变量修改。保证其变量访问的可见性和排他性。
2.2 通知/等待机制
可以确保及时性和降低开销。
相关方法:notify()、nitifyAll()、wait()、wait(long)、wait(long,int)。
注意点:1)使用notify()、nitifyAll()、wait()时需要先对调用对象加锁。2)notify()、nitifyAll()方法调用后,等待线程依旧不会从wait()方法返回,
需要调用notify()、nitifyAll()方法的线程,释放锁之后,等待线程才有机会从wait()返回。等待队列-》同步队列。3)wait()方法返回的前提是获取对象锁。
这种机制可以运用在生产者-消费者模式中。
package Thread; import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit; /**
* Created by Sky on 2016/9/22.
*
* @author xiaoyongyong
*/
public class WaitNotify {
static boolean flag = true;
static final Object lock = new Object(); public static void main(String[] args) throws Exception {
Thread waitTread = new Thread(new Wait(), "WaitTread");
waitTread.start();
TimeUnit.SECONDS.sleep(1); Thread notifyTread = new Thread(new NotifyTread(), "NotifyTread");
notifyTread.start();
} private static class Wait implements Runnable {
@Override
public void run() {
synchronized (lock) {
while (flag) {
try {
System.out.println(Thread.currentThread() + " flag is true.wait. " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread() + " flag is true.running. " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
}
}
} private static class NotifyTread implements Runnable {
@Override
public void run() {
synchronized (lock){
System.out.println(Thread.currentThread() + " hold lock.notify. " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
lock.notifyAll();
flag = false;
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (lock) {
System.out.println(Thread.currentThread() + " hold lock.again.sleep " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
返回结果:
Thread[WaitTread,5,main] flag is true.wait. 22:03:45
Thread[NotifyTread,5,main] hold lock.notify. 22:03:46
Thread[NotifyTread,5,main] hold lock.again.sleep 22:03:48
Thread[WaitTread,5,main] flag is true.running. 22:03:50
2.3 管道输入/输出流
主要用于线程之间的数据传输,传输媒介是内存,有PipedOutputStream/PipedInputStream(面向字节) 和PipedReader/PipedWriter(面向字符)。
package Thread; import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter; /**
* Created by Sky on 2016/9/22.
* @author xiaoyongyong
*/
public class Piped {
public static void main(String[] args) throws IOException {
PipedWriter out = new PipedWriter();
PipedReader in = new PipedReader();
out.connect(in);
Thread printThread = new Thread(new Print(in), "PringThread");
printThread.start(); int receive;
try {
while ((receive = System.in.read()) != -1) {
out.write(receive);
}
} finally {
out.close();
}
} private static class Print implements Runnable {
private PipedReader in;
public Print(PipedReader in) {
this.in = in;
}
@Override
public void run() {
int receive;
try {
while ((receive = in.read()) != -1) {
System.out.print((char) receive);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
输入一串字符串,按enter后,将原样输出。管道输入输出流必须先连接才可复制,即connect()。
2.4 Thread.join()的使用
当线程A等待thread线程终止之后,才从thread.join()返回。
join方法顾名思义 就是往线程中添加东西的;join方法可以用于临时加入线程,一个线程在运算过程中,如果满足于条件,我们可以临时加入一个线程,让这个线程运算完,另外一个线程再继续运行。
Thread,yeld()和Thread.sleep()的区别?
hread.yield()方法暂停当前正在执行的线程对象,并执行其他线程。也就是交出CPU一段时间(其他同样的优先级或者更高优先级的线程可以获取到运行的机会);不会释放锁资源。
而Thread.sleep()方法使当前线程进入停滞状态,所以执行sleep()的线程在指定的时间内肯定不会执行, 同时sleep函数不会释放锁资源;sleep可使优先级低的线程得到执行的机会,当然也可以让同优先级和高优先级的线程有执行的机会。
这两个的区别在于yield只能是同级,或者高级优先执行,而sleep可以低级,同级都可以有优先执行机会。
2.5 ThreadLocal的使用
线程变量,是一个以TreadLocal对象为键,任意对象为值得存储结构。
2.6 线程池技术及示例。
以下是线程池接口的定义和实现:
package Thread; /**
* Created by asus on 2016/9/27.
*/
public interface ThreadPool<Job extends Runnable> {
void execute(Job job);
void shutdown();
void addWorkers(int num);
void removeWoker(int num);
int getJobSize();
}
package Thread; import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong; /**
* Created by asus on 2016/9/27.
*
* @author xiaoyongyong
*/
public class DefaultThreadPool<Job extends Runnable> implements ThreadPool<Job> {
private static final int MAX_WORKER_NUMBERS = 10;
private static final int DEFAULT_WORKER_NUMBERS = 5;
private static final int MIN_WORKER_NUBERS = 1;
private final LinkedList<Job> jobs = new LinkedList<Job>();
private final List<Worker> workers = Collections.synchronizedList(new ArrayList<Worker>());
private int workerNum = DEFAULT_WORKER_NUMBERS;
private AtomicLong threadNum = new AtomicLong(); public DefaultThreadPool() {
initializeWorker(DEFAULT_WORKER_NUMBERS);
} private void DefaultThreadPool(int num) {
workerNum = num > MAX_WORKER_NUMBERS ? MAX_WORKER_NUMBERS : num < MIN_WORKER_NUBERS ? MAX_WORKER_NUMBERS : num;
initializeWorker(workerNum);
} @Override
public void execute(Job job) {
if (job != null) {
synchronized (jobs) {
jobs.add(job);
jobs.notify();
}
}
} @Override
public void shutdown() {
for (Worker worker : workers) {
worker.shutdown();
}
} @Override
public void addWorkers(int num) {
synchronized (jobs) {
if (num + this.workerNum > MAX_WORKER_NUMBERS) {
initializeWorker(num);
this.workerNum += num;
}
}
} @Override
public void removeWoker(int num) {
synchronized (jobs) {
if (num >= this.workerNum) {
throw new IllegalArgumentException("beyond workerNum");
}
int count = 0;
while (count < num) {
Worker worker = workers.get(count);
if (workers.remove(worker)) {
worker.shutdown();
count++;
}
}
this.workerNum -= count;
}
} @Override
public int getJobSize() {
return jobs.size();
} private void initializeWorker(int num) {
for (int i = 0; i < num; i++) {
Worker worker = new Worker();
workers.add(worker);
Thread threadWorker = new Thread(worker, "ThreadPool-Worker-" + threadNum.incrementAndGet());
threadWorker.start();
}
} class Worker implements Runnable {
private volatile boolean running = true; @Override
public void run() {
while (running){
Job job = null;
synchronized (jobs){
while (jobs.isEmpty()){
try {
jobs.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
return;
}
}
job = jobs.removeFirst();
}
if(job != null){
job.run();
}
}
} public void shutdown() {
running = false;
}
}
}
2.7 基于县此次技术的简单Web服务器
这个服务器使用main线程不断接受客户端Socket的连接,将连接以及请求交给线程池处理,这样使得Web服务器能够同同时处理多个客户端请求。
java并发编程基础---Sky的更多相关文章
- Java并发编程基础
Java并发编程基础 1. 并发 1.1. 什么是并发? 并发是一种能并行运行多个程序或并行运行一个程序中多个部分的能力.如果程序中一个耗时的任务能以异步或并行的方式运行,那么整个程序的吞吐量和可交互 ...
- 并发-Java并发编程基础
Java并发编程基础 并发 在计算机科学中,并发是指将一个程序,算法划分为若干个逻辑组成部分,这些部分可以以任何顺序进行执行,但与最终顺序执行的结果一致.并发可以在多核操作系统上显著的提高程序运行速度 ...
- Java并发编程--基础进阶高级(完结)
Java并发编程--基础进阶高级完整笔记. 这都不知道是第几次刷狂神的JUC并发编程了,从第一次的迷茫到现在比较清晰,算是个大进步了,之前JUC笔记不见了,重新做一套笔记. 参考链接:https:// ...
- Java并发编程基础-线程安全问题及JMM(volatile)
什么情况下应该使用多线程 : 线程出现的目的是什么?解决进程中多任务的实时性问题?其实简单来说,也就是解决“阻塞”的问题,阻塞的意思就是程序运行到某个函数或过程后等待某些事件发生而暂时停止 CPU 占 ...
- java并发编程基础概念
本次内容主要讲进程和线程.CPU核心数和线程数.CPU时间片轮转机制.上下文切换,并行和并发的基本概念以及并发编程的好处和注意事项,为java并发编程打下扎实基础. 1.什么是进程和线程 1.1 进程 ...
- 多线程(一)java并发编程基础知识
线程的应用 如何应用多线程 在 Java 中,有多种方式来实现多线程.继承 Thread 类.实现 Runnable 接口.使用 ExecutorService.Callable.Future 实现带 ...
- Java并发编程基础三板斧之Semaphore
引言 最近可以进行个税申报了,还没有申报的同学可以赶紧去试试哦.不过我反正是从上午到下午一直都没有成功的进行申报,一进行申报 就返回"当前访问人数过多,请稍后再试".为什么有些人就 ...
- Java并发编程基础之volatile
首先简单介绍一下volatile的应用,volatile作为Java多线程中轻量级的同步措施,保证了多线程环境中“共享变量”的可见性.这里的可见性简单而言可以理解为当一个线程修改了一个共享变量的时候, ...
- java并发编程基础——线程的创建
一.基础概念 1.进程和线程 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程.(进程是资源分配的最小单位) 线程:同一类线程共享代码和数据 ...
随机推荐
- ES6方面重点摘要
1.变量声明(1)内层变量覆盖外层变量(即后面的覆盖前面的)(2)循环变量的声明,i值在全局范围内有效,所以最后输出的都是最后一轮i的值(3)let.const的引入,为JS增加了块级作用域的概念(c ...
- 栅格 CSS中的循环 媒体查询
第三天Bootstrap 模态框 1.要使用模态框,需要现在body里,添加展示模态框的html代码.此时模态框是看不见的 2.如果要显示,$(“.modal”).modal(“show”); 3.如 ...
- [Functional Programming] Transition State based on Existing State using the State ADT (liftState, composeK)
While sometimes outside input can have influence on how a given stateful transaction transitions, th ...
- 模拟select控件&&显示单击的坐标&&用户按下键盘,显示keyCode
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- xtrabackup详解
xtrabackup是Percona公司CTO Vadim参与开发的一款基于InnoDB的在线热备工具,具有开源,免费,支持在线热备,备份恢复速度快,占用磁盘空间小等特点,并且支持不同情况下的多种备份 ...
- OpenStack二三事(1)
更新系列不是教材,不说教,不讲道理,仅仅记录. OpenStack在云计算领域大热,没有理由不去了解它. 先说说我对OpenStack的感觉,开源.廉价.麻烦.大家都在用,在了解开发流程后.OpenS ...
- 浅谈JavaScript变量声明提升
前段时间阿里实习生内推,一面就被刷了,也是郁闷.今天系统给发通知,大致意思就是内推环节不足以了解彼此,还可以参加笔试,于是赶紧再投一次.官网流程显示笔试时间3月31日,时间快到了,开始刷题.网上搜了一 ...
- NSNotification的几点说明
1.NSNotification消息的同步性 ①NSNotification使用的是同步操作.即如果你在程序中的A位置post了一个NSNotification,在B位置注册了一个observer,通 ...
- Laravel5.4使用Memcached缓存
修改默认的缓存驱动 Laravel默认的缓存驱动是file,想要切换为Memcached需要修改.env文件.把CACHE_DRIVER=file改为CACHE_DRIVER=memcached,改好 ...
- Python内置函数之staticmethod()
staticmethod(function)返回函数的静态方法.一般来说,实例对象调用类方法不用传入参数,因为实例对象本身隐式的作为第一个参数传入了.而采用静态方法之后,实例对象在调用类方法时必须传入 ...