一.先初步了解一下基本的概念
进程:在一个操作系统中,每个独立执行的程序都可以是一个进程。
线程:一个程序至少有一个进程,一个进程至少有一个线程,java里有一个主线程和垃圾回收线程。
线程的3中创建方式:
1.继承Thread类
2.实现Runnable接口
3.实现Callable接口,和Future、线程池一起使用
线程的优先级:
优先级的返回是1-10,默认是5,数越大优先级越高。
join的作用是:
等待该线程终止,指的是主线程等待子线程的终止。子线程调用了join方法,只有子线程执行完之后才会调用主线程。(主线程需要用到子线程的处理结果是使用join)
二.多线程之间的状态转换
状态之间装换的demo:
package cn;
public class ThreadDemo extends Thread {
private boolean runningFlag=false;
public ThreadDemo(){
runningFlag = false;
}
public synchronized void setRunningFlag(boolean runningFlag) {
this.runningFlag = runningFlag;
if(runningFlag){
this.notify();
}else{
try {
System.out.println("线程"+Thread.currentThread().getName()+"开始等待");
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void run() {
sayHello();
}
//锁池状态
public synchronized void sayHello(){
while(true){
if(!runningFlag){
try {
System.out.println("线程"+Thread.currentThread().getName()+"开始等待");
this.wait();//等待状态
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
try {
sleep(3000);//堵塞状态
System.out.println("线程"+Thread.currentThread().getName()+"任务完成\n");
setRunningFlag(false); //让当前线程处于等待任务状态
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
int i=10;
while (i-->0) {
//新建创建
ThreadDemo demo=new ThreadDemo();
demo.setName("demo"+i);
demo.setRunningFlag(true);
//可运行状态,start之后等待cpu获取时间片
demo.start();
}
}
}
三.使用Callable接口,和Future、线程池计算1-100的和
package cn;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ThreadAddFuture {
public static List<Future> futureList=new ArrayList<Future>();
public static void main(String[] args) throws InterruptedException, ExecutionException {
int sum=0;
ThreadAddFuture add=new ThreadAddFuture();
//创建线城池
ExecutorService pool=Executors.newFixedThreadPool(4);
for (int i =1; i <=76;) {
ThreadTest thread=add.new ThreadTest(i,i+24);
//接收线程的返回值
Future<Integer> future=pool.submit(thread);
futureList.add(future);
i+=25;
}
if(futureList!=null && futureList.size()>0){
for(Future<Integer> future:futureList){
sum+=(Integer)future.get();
}
}
System.out.println("total result: "+sum);
pool.shutdown();
}
//实现Callable接口
class ThreadTest implements Callable<Integer>{
private int begin;
private int end;
private int sum=0;
public ThreadTest(int begin,int end){
this.begin=begin;
this.end=end;
}
@Override
public Integer call() throws Exception {
for (int i =begin; i <=end; i++) {
sum+=i;
}
System.out.println("from "+Thread.currentThread().getName()+" sum="+sum);
return sum;
}
}
}
四.使用runnable、CountDownLatch、线程池的demo
CountDownLatch:CountDownLatch是一个同步的辅助器是一个计数器,只要计数器为0主线程就可以结束堵塞进行执行,和join很像但是比join更加灵活。
package cn;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class WatchThread {
private String name=UUID.randomUUID().toString();
public void testThread() throws InterruptedException{
int threadNum=10;
//初始化countDown
CountDownLatch threadSignal=new CountDownLatch(threadNum);
ExecutorService executor=Executors.newFixedThreadPool(threadNum);
for (int i = 0; i <threadNum; i++) {
TestThread task=new TestThread(threadSignal);
//执行
executor.execute(task);
}
threadSignal.await();
executor.shutdown();
System.out.println(Thread.currentThread().getName() + "+++++++结束.");
}
public static void main(String[] args) throws InterruptedException{
WatchThread test=new WatchThread();
test.testThread();
}
private class TestThread implements Runnable{
private CountDownLatch threadsSignal;
public TestThread(CountDownLatch threadsSignal){
this.threadsSignal=threadsSignal;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "开始..." + name);
System.out.println("开始了线程::::" + threadsSignal.getCount());
threadsSignal.countDown();//必须等核心处理逻辑处理完成后才可以减1
System.out.println(Thread.currentThread().getName() + "结束. 还有"
+ threadsSignal.getCount() + " 个线程");
}
}
}
五.synchronized的实现原理
synchronized实现同步的基础:java中的每一个对象都可以是锁,主要有3种形式:
. 对于普通同步方法,锁的是实例对象。
.对于静态同步方法,锁的是当前类的Class对象。
. 对于同步代码块,锁的是括号里配置的对象。
JVM是基于进入和退出Moniter对象来实现同步和代码块同步的,同步代码块是基于monitorenter和monitorexit实现的,同步方法ACC_synchronized实现的,monitorenter放在同步代码块的开始位置,monitorexit放在同步代码块的结束位置,必须是成对出现的。当前一个moniter被持有后,它将处于锁定状态,线程执行到moniteorenter时,获得monitor的所有权,所得对象的锁。
synchronized获得的锁是存放在对象头里的,堆中的对象由对象头,实例变量和填充数据组成。对象头的markword存储的是HashCode、分代年龄和锁标记位,锁标记位有无锁状态、偏向锁、轻量级锁、重量级锁。对象头还会存储是否是偏向锁的标识。