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. Java源码阅读HashMap

    1类签名与注释 public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cl ...

  2. thrift.transport.TTransport.TTransportException: Could not start SASL: Error in sasl_client_start (-4) SASL(-4): no mechanism available: No worthy mechs found

    thrift.transport.TTransport.TTransportException: Could not start SASL: Error in sasl_client_start (- ...

  3. setlocal启动批处理文件中环境变量的本地化

    setlocal启动批处理文件中环境变量的本地化 在执行 SETLOCAL 之后所做的环境改动只限于批处理文件.要还原原先的设置,必须执行 ENDLOCAL. 学习了:https://baike.ba ...

  4. AndroidStudio快捷键大全

    很多近期学习移动开发的朋友都是通过Eclipse集成ADT开发安卓程序.但是谷歌已经推出了自己的亲儿子--Android Studio.可以说比原来的开发工具强大很多,现在各大公司也已经逐渐淘汰了Ec ...

  5. TestNG+ReportNG+IDEA+Git+Jenkins+surefire持续集成数据驱动dubbo接口测试

    一.pom.xml增加testng相关配置 <!--添加插件 关联testNg.xml--><plugin> <groupId>org.apache.maven.p ...

  6. JavaScript数组归并方法reduce

    示例代码: <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF ...

  7. <转>Windows平台下Makefile学习笔记(一)

    本文转自:http://blog.csdn.net/clever101/article/details/8147352 决心学习Makefile,一方面是为了解决编译开源代码时需要跨编译平台的问题(发 ...

  8. 用unity3d实现简单的主server连接

    用unity3d实现简单的主server连接 參考自鹰大的网络实例 -------------------------------------------------华丽的切割线----------- ...

  9. StringUtils工具类详解

    StringUtils判断字符串大概有四种方法: 下面是 StringUtils 判断是否为空的示例: 判断是否为空,但是要注意,空格不算空,这个最好能不用则不用. StringUtils.isEmp ...

  10. Spring4整合Hibernate5时不能自动生成表结构

    © 版权声明:本文为博主原创文章,转载请注明出处 1.问题描述: Spring4整合Hibernate5时,不再使用hibernate.cfg.xml,将其内容整合到Spring配置文件中,启动后不能 ...