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的更多相关文章

  1. Java并发编程基础

    Java并发编程基础 1. 并发 1.1. 什么是并发? 并发是一种能并行运行多个程序或并行运行一个程序中多个部分的能力.如果程序中一个耗时的任务能以异步或并行的方式运行,那么整个程序的吞吐量和可交互 ...

  2. 并发-Java并发编程基础

    Java并发编程基础 并发 在计算机科学中,并发是指将一个程序,算法划分为若干个逻辑组成部分,这些部分可以以任何顺序进行执行,但与最终顺序执行的结果一致.并发可以在多核操作系统上显著的提高程序运行速度 ...

  3. Java并发编程--基础进阶高级(完结)

    Java并发编程--基础进阶高级完整笔记. 这都不知道是第几次刷狂神的JUC并发编程了,从第一次的迷茫到现在比较清晰,算是个大进步了,之前JUC笔记不见了,重新做一套笔记. 参考链接:https:// ...

  4. Java并发编程基础-线程安全问题及JMM(volatile)

    什么情况下应该使用多线程 : 线程出现的目的是什么?解决进程中多任务的实时性问题?其实简单来说,也就是解决“阻塞”的问题,阻塞的意思就是程序运行到某个函数或过程后等待某些事件发生而暂时停止 CPU 占 ...

  5. java并发编程基础概念

    本次内容主要讲进程和线程.CPU核心数和线程数.CPU时间片轮转机制.上下文切换,并行和并发的基本概念以及并发编程的好处和注意事项,为java并发编程打下扎实基础. 1.什么是进程和线程 1.1 进程 ...

  6. 多线程(一)java并发编程基础知识

    线程的应用 如何应用多线程 在 Java 中,有多种方式来实现多线程.继承 Thread 类.实现 Runnable 接口.使用 ExecutorService.Callable.Future 实现带 ...

  7. Java并发编程基础三板斧之Semaphore

    引言 最近可以进行个税申报了,还没有申报的同学可以赶紧去试试哦.不过我反正是从上午到下午一直都没有成功的进行申报,一进行申报 就返回"当前访问人数过多,请稍后再试".为什么有些人就 ...

  8. Java并发编程基础之volatile

    首先简单介绍一下volatile的应用,volatile作为Java多线程中轻量级的同步措施,保证了多线程环境中“共享变量”的可见性.这里的可见性简单而言可以理解为当一个线程修改了一个共享变量的时候, ...

  9. java并发编程基础——线程的创建

    一.基础概念 1.进程和线程 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程.(进程是资源分配的最小单位) 线程:同一类线程共享代码和数据 ...

随机推荐

  1. Webdriver如何启动不同浏览器(python)

    WebDriver 支持 Firefox (FirefoxDriver).IE (InternetExplorerDriver).Opera (OperaDriver) 和 Chrome (Chrom ...

  2. 智能选择器和语义化的CSS

    本文由白牙根据Heydon Pickering的<Semantic CSS With Intelligent Selectors>所译,整个译文带有我自己的理解与思想,如果译得不好或不对之 ...

  3. 机器学习入门之四:机器学习的方法--SVM(支持向量机)(转载)

    转自 飞鸟各投林 SVM(支持向量机) 支持向量机算法是诞生于统计学习界,同时在机器学习界大放光彩的经典算法. 支持向量机算法从某种意义上来说是逻辑回归算法的强化:通过给予逻辑回归算法更严格的优化条件 ...

  4. SSO单点登录系列3:cas-server端配置认证方式实践(数据源+自定义java类认证)

    落雨 cas 单点登录 本篇将讲解cas-server端的认证方式 1.最简单的认证,用户名和密码一致就登录成功 2.配置Oracle的jdbc数据源,通过spring动态查询数据库 3.配置orac ...

  5. .net平台 基于 XMPP协议的即时消息服务端简单实现

    .net平台 基于 XMPP协议的即时消息服务端简单实现 昨天抽空学习了一下XMPP,在网上找了好久,中文的资料太少了所以做这个简单的例子,今天才完成.公司也正在准备开发基于XMPP协议的即时通讯工具 ...

  6. Effective C++ 条款17

    以独立语句将newed对象置入智能指针 本节我们须要学习的知识核心是注意编译器在同一语句中,调用次序具有不确定性,不同语句中,调用次序确定. 上面的话什么意思? 请看下面代码: int priorit ...

  7. iOS音乐后台播放及锁屏信息显示

    实现音乐的后台播放.以及播放时,能够控制其暂停,下一首等操作,以及锁屏图片歌曲名等的显示 此实例须要真机调试.效果图例如以下: project下载:githubproject下载 实现步骤: 1.首先 ...

  8. 斯坦福《机器学习》Lesson5感想———1、成学习算法

    在前面几课里的学习算法的思路都是给定数据集以后.确定基于此数据集的最佳如果H函数,通过学习算法确定最佳如果H的各个參数,然后通过最佳如果函数H得出新的数据集的结果.在这一课里介绍了一种新的思路,它的核 ...

  9. SQL语句练习手册--第三篇

    一.CASE的两种用法 1.1 等值判断->相当于switch case (1)具体用法模板: CASE expression WHEN value1 THEN returnvalue1 WHE ...

  10. Mysql5.6压缩包安装到windows&& 卸载命令

    1.根目录下有一个my-default.ini,复制一下,重命名为my.ini,然后改一下my.ini为符合你情况的配置,一般只需要改basedir .datadir .port ,注意前边的井号去掉 ...