目录
1、什么是线程
2、线程的基本操作
3、基本的线程同步操作
1.1 进程、线程概念:
1、进程:一个计算机程序的运行实例,有自己的独立地址空间。
2、线程:表示程序的执行流程,是CPU调度执行的基本单位;同一进程中的线程共用相同的地址空间。
线程状态
2.1线程状态:包括以下图中五种
第一种方式:使用Runnable接口创建线程;
第二种方式:直接继承Thread类创建对象;
实例代码:
package creatthreadtwo;
public class MyThread1 extends Thread {
public void run(){
System.out.println("1");
}
public static void main(String[] args) {
MyThread1 mThread=new MyThread1();
mThread.start();
}
}
package creatthreadtwo;
public class MyThread2 implements Runnable {
@Override
public void run() {
System.out.println("1");
}
public static void main(String[] args) {
Thread mThread=new Thread(new MyThread2());
mThread.start();
}
}
4.1 常见的线程方法讲解:
1、Thread.stop():不推荐使用stop方法来终止线程,它会释放所有的锁资源
实例代码:
package leranstop; public class StopThread { public static void main(String[] args) throws Exception { Thread thread = new Thread() { @Override public void run () { try { //子线程休眠1秒 Thread.sleep(1000); } catch (InterruptedException e) { //异常处理 } System.out.println ("此处代码不会执行"); } }; //启动线程 thread.start(); //主线程休眠0.1秒 Thread.sleep(100); //子线程停止 thread.stop(); }
}
}
2、Thread.interrupt():该方法中断线程,它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。
而isInterrupted()通过中断手段在运行中来判断线程是否中断来终止线程,但是必须重设中断标志位。
实例代码:
package learninterrput;
public class Main {
public static void main(String[] args) {
Main main = new Main();
Thread t = new Thread(main.runnable);
System.out.println("mainmainmain");
t.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t.interrupt();
System.out.println("sososososo");
}
Runnable runnable = new Runnable() {
@Override
public void run() {
int i = 0;
try {
while (i < 1000) {
Thread.sleep(200);
System.out.println(i++);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程");
}
};
}
3、suspend():线程挂起,阻塞状态,不会释放锁
4、resume():线程继续执行执行
5、join():当某个程序执行流中调用其他线程的join()方法时,调用线程将被阻塞,直到被join方法加入的join线程完成为止。
6、sleep():让当前正在执行的线程暂停一段时间并进入阻塞状态。
实例代码:
package leranjoin;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public class LeranJoin {
public static void main(String[] args) {
//t1产生10个随机数填充到list
//t2加入t1 等到t1线程完成以后对list进行排序
//在t2线程中 t1.join(),实现t2等待t1的结束
final List<Integer> list=new ArrayList<Integer>();
final Thread t1=new Thread(){
public void run(){
Random r=new Random();
for(int i=0;i<10;i++){
list.add(r.nextInt(100));
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("执行一次...");
}
}
};
final Thread t2=new Thread(){
public void run(){
System.out.println("t2 start...");
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}//当前线程等待t1结束
System.out.println("t1结束了");
Collections.sort(list);
System.out.println(list);
}
};
t1.start();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
}
}
执行的机;设置线程优先级的方法---setPriority()。
8、setDaemon(true):设置守护线程,当一个java应用内,只有守护线程的时候,jvm就会自然退出。
实例代码:
package learnwaitornotifyordaemo;
public class DaemonDemo extends Thread{
public void run(){
while(true){
System.out.println("继续");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
DaemonDemo t=new DaemonDemo();
t.setDaemon(true);
t.start();
}
}
9、wait():导致当前的线程等待,会释放其拥有的锁,直到其他线程调用此对象的notify() 方法或 notifyAll() 方法。当前的线程必须拥有此对象监视器(锁)。
10、notify():唤醒在此对象监视器上(锁)等待的单个线程。
11、notifyAll():唤醒在此对象监视器上(锁)等待的所有个线程。
实例代码:
package learnwaitornotifyordaemo;
public class LeranwaitOrnotify {
final static Object object=new Object();
final static Object object2=new Object();
public static class T1 extends Thread{
public void run(){
synchronized (object) {
System.out.println("T1 start wait on object");
try {
object.wait();
System.out.println("T1 end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static class T2 extends Thread{
public void run(){
synchronized (object) {
System.out.println("T2 start notify all threads");
object.notify();
System.out.println("T2 end");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static class T3 extends Thread{
public void run(){
synchronized (object) {
System.out.println("T3 start wait one threads");
try {
object.wait();
System.out.println("T3 end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Thread t1=new T1();
Thread t2=new T2();
Thread t3=new T3();
t1.start();
t3.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
}
}
5.1 线程安全同步、异步
1、同步:就是指多个线程在逻辑上互有前因后果的关系,一个线程要等待上一个线程执行完之后才开始执行当前的线程
2、异步:是指一个线程去执行,它的下一个线程不必等待它执行完就开始执行
3、并发:在同一时间间隔内有多个线程在同时执行,就是线程的并发
实例代码:
6.1 线程安全同步机制
1、同步关键字:synchronized,对共享需要锁定的资源加上该关键字--即为同步监视器
1)、指定加锁对象;对给定对象加锁,进入同步代码块前要获得给定对象的锁
2)、对当前类加锁,进入同步代码块前要获得当前类的锁
3)、直接作用于实例方法;对当前实例加锁,进入同步代码块前要获得当前实例的锁直接作用于静态的方法;
实例代码:
package learnsynchonized;
public class MyThread extends Thread{
private int count=5;
public synchronized void run(){
count--;
System.out.println(Thread.currentThread().getName()+"----count: "+count);
}
public static void main(String[] args) {
MyThread t=new MyThread();
Thread t1=new Thread(t,"t1");
Thread t2=new Thread(t,"t2");
Thread t3=new Thread(t,"t3");
Thread t4=new Thread(t,"t4");
Thread t5=new Thread(t,"t5");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
2、volatile:是JAVA中的轻量级的同步机制;注意:保证可见性,但不能保证原子性
实例代码:
package learnvolatile;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomictyVolatile extends Thread{
public volatile int race = 0;
@Override
public void run() {
increase();
}
private synchronized void increase() { //synchronized
race ++;
System.out.println(race);
}
public static void main(String[] args) {
AtomictyVolatile t = new AtomictyVolatile();
Thread [] threads = new Thread[10];
for (int i = 0; i < 10; i++) {
threads[i] = new Thread(t);
threads[i].start();
}
//保证打印的时候1000个线程都已经执行完毕
}
}
3、lock显示加锁,进行同步:java也可以用Lock显示的对临界区代码加锁以及解锁
实例代码:
package leranlock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import learnsynchonized.MyThread;
public class MyLock implements Runnable{
private int count=5;
private Lock lock=new ReentrantLock();
//private ReadWriteLock rwLock=new ReentrantReadWriteLock();
public void run(){
lock.lock();
try{
count--;
System.out.println(Thread.currentThread().getName()+"----count: "+count);
}catch(Exception e){
//DOTO
}finally{
lock.unlock();
}
}
public static void main(String[] args) {
MyLock t=new MyLock();
Thread t1=new Thread(t,"t1");
Thread t2=new Thread(t,"t2");
Thread t3=new Thread(t,"t3");
Thread t4=new Thread(t,"t4");
Thread t5=new Thread(t,"t5");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
7.1 线程安全 脏读、线程池
1、脏读:就是一个线程的所访问的资源没处理完成,另一个线程过来访问这些资源,就会导致脏读,如读写线程操作等。
实例代码:
package learndirtyread;
public class DirtyRead{
private String username="bjsxt";
private String password="123";
public synchronized void setValue(String username,String password){
this.username=username;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.password=password;
System.out.println("setValue 最终结果为: username= "+username+",password= "+password);
}
public synchronized void getValue(){
System.out.println("getValue 方法得到结果为: username= "+username+",password= "+password);
}
public static void main(String[] args) {
final DirtyRead dd = new DirtyRead();
Thread t1=new Thread(new Runnable(){
@Override
public void run() {
dd.setValue("zs", "456");
}
});
t1.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
dd.getValue();
//System.exit(1);
}
}
2、线程池
线程池:JDK提供一套线程框架Execute,来管理线程,通过Execute创建特定功能的线程池方法。
优点:
a. 重用存在的线程,减少对象创建、消亡的开销,性能佳。
b. 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
c. 提供定时执行、定期执行、单线程、并发数控制等功能。
实例代码:
package leranthreadpool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPool {
/**
*
* 1)、创建两个固定数量线程的线程池
* 2)、为线程提交10个工作任务
* 3)、每个任务每隔一秒输出1,2,3,并输出线程名
* concurrent:并发包下的
* 测试结果:只有两个线程并发执行
* Executors 是ExecutorService工厂
*/
public static void main(String[] args) {
ExecutorService pool=Executors.newFixedThreadPool(2);
//创建任务交给线程池执行(execute : 执行)
pool.execute(new Task());
pool.execute(new Task());
pool.execute(new Task());
pool.execute(new Task());
pool.execute(new Task());
pool.execute(new Task());
pool.execute(new Task());
pool.execute(new Task());
pool.execute(new Task());
pool.execute(new Task());
}
}
/**
*交给线程池执行的任务必须实现 Runnable 接口
*/
class Task implements Runnable{
@Override
public void run() {
Thread t=Thread.currentThread();
try {
System.out.println(t.getName()+":1");
Thread.sleep(500);
System.out.println(t.getName()+":2");
Thread.sleep(500);
System.out.println(t.getName()+":3");
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
8.1 线程安全 消息队列、模式
1、在并发队列上JDK提供了两套实现,一个是ConcurrentLinkedQueue为代表的高性能队列,一个是BlockingQueue为接口的阻塞队列,都继承Queue。
2、模式future模式,master-work模式,生产者--消费者模式。
实例代码:
package xchengreadfile;
public class MyThread implements Runnable {
@Override
public void run() {
System.out.println("1");
}
public static void main(String[] args) {
Thread mThread=new Thread(new MyThread());
mThread.start();
}
}
package xchengreadfile;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadReadDemo2 {
/**
* @param args
*/
public static void main(String[] args) {
int count=getLineInt();
ExecutorService pool=Executors.newFixedThreadPool(5);
for(int i=0;i<10;i++){
pool.execute(new Task());
}
}
public static int getLineInt(){
int x=0;
try {
FileReader fr = new FileReader("E://ceshi.txt");
BufferedReader br = new BufferedReader(fr);
while(br.readLine()!=null){
x++;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return x;
}
}
class Task extends Thread{
}
联系客服