进程
线程是依赖于进程而存在的
线程
多线程的实现方式
package com.thread;
public class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i <100 ; i++) {
System.out.println(i);
}
}
}
package com.thread;
public class ThreadTest01 {
public static void main(String[] args) {
MyThread th1 = new MyThread();
MyThread th2 = new MyThread();
// th1.run();
// th2.run();
//public void start()导致此线程开始执行
th1.start();
th2.start();
}
}
设置和获取线程名称
package com.thread;
public class MyThread extends Thread {
MyThread() {
}
MyThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName() + ":" + i);
}
}
}
/*
private String name;
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
this.name = name;
}
public final String getName() {
return name;
}
public final synchronized void setName(String name) {
this.name = name;
}
private static int threadInitNumber;//0,1,2
private static synchronized int nextThreadNum() {
//先执行 ,后自增
return threadInitNumber++;//0,1
}
*
* */
package com.thread;
public class ThreadTest01 {
public static void main(String[] args) {
MyThread th1 = new MyThread("高铁");
MyThread th2 = new MyThread("飞机");
// th1.run();
// th2.run();
//public void start()导致此线程开始执行; Java虚拟机调用此线程的run方法。
//public final void setName(String name)将此线程的名称更改为等于参数name 。
// th1.setName("高铁");
// th2.setName("飞机");
// th1.start();
// th2.start();
//static Thread currentThread() 返回对当前正在执行的线程对象的引用。
System.out.println(Thread.currentThread().getName());
}
}
线程调度
package com.thread;
public class ThreadPriorityTest01 {
public static void main(String[] args) {
//void setPriority(int newPriority) 更改此线程的优先级。
//int getPriority() 返回此线程的优先级。
ThreadPriority tp1 = new ThreadPriority();
ThreadPriority tp2 = new ThreadPriority();
ThreadPriority tp3 = new ThreadPriority();
tp1.setName("高铁");
tp2.setName("飞机");
tp3.setName("火车");
/* System.out.println(tp1.getPriority());//5
System.out.println(tp2.getPriority());//5
System.out.println(tp3.getPriority());//5*/
//tp1.setPriority(10000);//IllegalArgumentException IllegalArgumentException - 如果优先级不在 MIN_PRIORITY到 MAX_PRIORITY范围内。
// System.out.println(Thread.MIN_PRIORITY);//1
// System.out.println(Thread.MAX_PRIORITY);//10
// System.out.println(Thread.NORM_PRIORITY);//5
tp1.setPriority(1);
tp2.setPriority(10);
tp3.setPriority(5);
tp1.start();
tp2.start();
tp3.start();
}
}
线程控制
package com.thread;
public class ThreadSleep extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName()+":"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package com.thread;
public class ThreadSleepTest01 {
//static void sleep(long millis) 使当前正在执行的线程停留(暂停执行)指定的毫秒数,这取决于系统定时器和调度程序的精度和准确性。
public static void main(String[] args) {
ThreadSleep ts1 = new ThreadSleep();
ThreadSleep ts2 = new ThreadSleep();
ThreadSleep ts3 = new ThreadSleep();
ts1.setName("曹操");
ts2.setName("刘备");
ts3.setName("孙权");
ts1.start();
ts2.start();
ts3.start();
}
}
package com.thread;
public class ThreadJion extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName()+":"+i);
}
}
}
package com.thread;
public class ThreadJionTest01 {
public static void main(String[] args) {
ThreadJion tj1 = new ThreadJion();
ThreadJion tj2 = new ThreadJion();
ThreadJion tj3 = new ThreadJion();
tj1.setName("康熙");
tj2.setName("四阿哥");
tj3.setName("八阿哥");
//void join() 等待这个线程死亡。
tj1.start();
try {
tj1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
tj2.start();
tj3.start();
}
}
package com.thread;
public class ThreadDaemo extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName()+":"+i);
}
}
}
package com.thread;
public class ThreadDaemoTest01 {
public static void main(String[] args) {
// void setDaemon(boolean on) 将此线程标记为 daemon线程或用户线程。
ThreadDaemo td1 = new ThreadDaemo();
ThreadDaemo td2 = new ThreadDaemo();
//设置主线程
Thread.currentThread().setName("刘备");
td1.setName("张飞");
td2.setName("关羽");
//设置守护线程
td1.setDaemon(true);
td2.setDaemon(true);
td1.start();
td2.start();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
线程的生命周期
多线程的实现方式二
package com.thread.lesson02;
public class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
package com.thread.lesson02;
public class MyRunnableTest01 {
public static void main(String[] args) {
//创建MyRunnable类对象
MyRunnable mr1 = new MyRunnable();
//创建Thread类对象,把MyRunnable类作为构造方法的参数传递
//Thread(Runnable target) 分配一个新的 Thread对象。
// Thread th1 = new Thread(mr1);
// Thread th2 = new Thread(mr1);
//Thread(Runnable target, String name) 分配一个新的 Thread对象。
Thread th1 = new Thread(mr1,"高铁");
Thread th2 = new Thread(mr1,"飞机");
th1.start();
th2.start();
}
}
线程同步
卖票
package com.thread.lesson02;
//定义一个类SellTicket实现Runnable接口,里面定义一个成员变量: private int tickets=100
public class SellTicket implements Runnable{
private int tickets=100;
//在SellTicket类中重写run()方法实现卖票
@Override
public void run() {
//A:判断票数打于0,就卖票,并告知是哪个窗口卖的
//B:卖了票之后,总票数要减一
//C:票没有了,也可能有人来问,所以这里用死循环让卖票的动作一直执行
while (true){
if (tickets>0){
System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
tickets--;
}
}
}
}
package com.thread.lesson02;
public class SellTicketDemo {
public static void main(String[] args) {
//创建SellTicket类的对象
SellTicket st = new SellTicket();
//创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称
Thread th1 = new Thread(st,"窗口1");
Thread th2 = new Thread(st,"窗口2");
Thread th3 = new Thread(st,"窗口3");
//启动线程
th1.start();
th2.start();
th3.start();
}
}
卖票案例的出现的问题
package com.thread.lesson02;
//定义一个类SellTicket实现Runnable接口,里面定义一个成员变量: private int tickets=100
public class SellTicket implements Runnable{
private int tickets=100;
//在SellTicket类中重写run()方法实现卖票
@Override
public void run() {
//相同的票出现了多次
/* while (true){
//tickets=100
//t1,t2,t3
//假设t1线程抢到CPU的执行权
if (tickets>0){
//通过sleep()方法来模拟出票时间
try {
Thread.sleep(100);
//t1线程休息100毫秒
//t2线程抢到了CPU的执行权,t2执行到这里的时候,t2线程休息100毫秒
//t3线程抢到了CPU的执行权,t3执行到这里的时候,t3线程休息100毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
//假设线程按照顺序醒过来
//t1抢到CPU的执行权,在控制台输出:窗口1正在出售第100张票
System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
//t2抢到CPU的执行权,在控制台输出:窗口2正在出售第100张票
//t3抢到CPU的执行权,在控制台输出:窗口3正在出售第100张票
tickets--;
//如果这三个线程还是按照顺序来,这里就执行了3次--的操作,最终票就变成了97
}
}*/
//出现了负数的票
while (true){
//tickets=1;
//t1,t2,t3
//假设t1线程抢到CPU的执行权
if (tickets>0){
//通过sleep()方法来模拟出票时间
try {
Thread.sleep(100);
//t1线程休息100毫秒
//t2线程抢到了CPU的执行权,t2执行到这里的时候,t2线程休息100毫秒
//t3线程抢到了CPU的执行权,t3执行到这里的时候,t3线程休息100毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
//假设线程按照顺序醒过来
//t1抢到CPU的执行权,在控制台输出:窗口1正在出售第1张票
//假设t1继续拥有CPU的执行权,就会执行tickets--;操作,tickets=0;
//t2抢到CPU的执行权,在控制台输出:窗口2正在出售第0张票
//假设t1继续拥有CPU的执行权,就会执行tickets--;操作,tickets=-1;
//t3抢到CPU的执行权,在控制台输出:窗口3正在出售第-1张票
//假设t1继续拥有CPU的执行权,就会执行tickets--;操作,tickets=-2;
System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
tickets--;
}
}
}
}
卖票案例数据安全问题的解决
同步代码块
package com.thread.lesson02;
public class SellTicket implements Runnable {
private int tickets = 100;
private Object obj = new Object();
@Override
public void run() {
while (true) {
//tickets=100;
//t1,t2,t3
//假设t1抢到了CPU的执行权
//假设t2抢到了CPU的执行权
synchronized (obj) {
if (tickets > 0) {
//t1进来后,就会把这段代码给锁起来
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
}
}
}
}
}
package com.thread.lesson02;
public class SellTicketDemo {
public static void main(String[] args) {
//创建SellTicket类的对象
SellTicket st = new SellTicket();
//创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称
Thread th1 = new Thread(st,"窗口1");
Thread th2 = new Thread(st,"窗口2");
Thread th3 = new Thread(st,"窗口3");
//启动线程
th1.start();
th2.start();
th3.start();
}
}
同步方法
package com.thread.lesson02;
public class SellTicket implements Runnable {
private static int tickets = 100;
private Object obj = new Object();
private int x = 0;
@Override
public void run() {
while (true) {
if (x % 2 == 0) {
// synchronized (obj) {
// synchronized (this) {
// SellTicket.class 该类的字节码文件对象
synchronized (SellTicket.class) {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
}
}
} else {
// synchronized (obj) {
// if (tickets > 0) {
//
// try {
// Thread.sleep(100);
//
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
//
// System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
//
// tickets--;
// }
// }
sellTicket();
}
x++;
}
}
// private void sellTicket() {
// synchronized (obj) {
// if (tickets > 0) {
//
// try {
// Thread.sleep(100);
//
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
//
// System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
//
// tickets--;
// }
// }
// private synchronized void sellTicket() {
//
// if (tickets > 0) {
//
// try {
// Thread.sleep(100);
//
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
//
// System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
//
// tickets--;
// }
//
private static synchronized void sellTicket() {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
}
}
}
线程安全的类
package com.thread.lesson03;
import java.util.*;
public class TheadTest {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer();
StringBuilder sb2 = new StringBuilder();
Vector<String> v = new Vector<>();
ArrayList<String> list = new ArrayList<>();
Hashtable<String, String> ht = new Hashtable<>();
HashMap<String, String> hm = new HashMap<>();
List<String> list1 = Collections.synchronizedList(new ArrayList<String>());
}
}
Lock锁
package com.thread.lesson03;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//void lock() 获得锁。
//void unlock() 释放锁。
//Lock是接口不能直接实例化,这里采用它的实现类 ReentrantLock来实例化
// ReentrantLock() 创建一个 ReentrantLock的实例。
public class SellTicket implements Runnable {
private static int tickets = 100;
private Lock lock=new ReentrantLock();
@Override
public void run() {
while (true) {
lock.lock();
try {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
}
}finally {
lock.unlock();
}
}
}
}
package com.thread.lesson03;
import com.thread.lesson02.SellTicket;
public class SellTicketDemo {
public static void main(String[] args) {
//创建SellTicket类的对象
com.thread.lesson02.SellTicket st = new SellTicket();
//创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称
Thread th1 = new Thread(st,"窗口1");
Thread th2 = new Thread(st,"窗口2");
Thread th3 = new Thread(st,"窗口3");
//启动线程
th1.start();
th2.start();
th3.start();
}
}
生产者和消费者
生产者和消费者模式概述
生产者生产数据但消费者可能没有消费数据这时就会提醒他快来消费
消费者想要消费数据但是生产者没有生产数据这时就会提醒他快生产数据
生产者和消费者案例
package com.thread.lesson04;
public class Box {
//定义一个成员变量,表示第x瓶奶,
int milk = 0;
//定义一个成员变量,表示奶箱状态
boolean state = false;
//提供存储牛奶和获取牛奶的操作
public synchronized void put(int milk) throws InterruptedException {
//如果有,我们就等待消费
if (state) {
wait();
}
//如果没有,就生产
this.milk = milk;
System.out.println("送奶工将第" + this.milk + "瓶奶放入奶箱");
//生产完毕之后,改变奶箱状态
state = true;
//唤醒其他等待线程
notifyAll();
}
public synchronized void get() throws InterruptedException {
//如果没有,就等待生产
if (!state) {
wait();
}
//如果有,就消费
System.out.println("消费者获得第" + this.milk + "瓶奶");
//消费完毕之后,改变奶箱状态
state = false;
//唤醒其他等待线程
notifyAll();
}
}
package com.thread.lesson04;
public class Customer implements Runnable {
private Box b;
public Customer(Box b) {
this.b = b;
}
@Override
public void run() {
while (true) {
try {
b.get();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package com.thread.lesson04;
public class Producer implements Runnable {
private Box b;
public Producer(Box b) {
this.b = b;
}
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
try {
b.put(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package com.thread.lesson04;
public class BoxTest {
public static void main(String[] args) {
//创建奶箱对象,这是共享数据区域
Box b = new Box();
//创建生产者对象,把奶箱对象作为构造方法参数传递
Producer p = new Producer(b);
//创建消费者对象,把奶箱对象作为构造方法参数传递
Customer c = new Customer(b);
Thread th1 = new Thread(p);
Thread th2 = new Thread(c);
//启动线程
th1.start();
th2.start();
}
}