1.实现多线程
1.1 进程
进程:是正在运行的程序
是系统进行资金分配和调用的独立单位
每一个进度都有它自己的内存空间和系统资源
1.2 线程
线程:是进程中的单个顺序控制流,是一条执行路径
单线程:一个进程如果只有一条执行路径,则称为单线程程序
多线程:如果一个进程有多条执行路径,则成为多线程程序
举例:
记事本
扫雷程序
1.3 多线程的实现方式
package mythread;
public class MyThread extends Thread{
@Override
public void run(){
for(int i=0;i<100;i++){
System.out.println(i);
}
}
}
package mythread;
public class MyThreadDemo {
public static void main(String[] args) {
MyThread my1= new MyThread();
MyThread my2= new MyThread();
//调用run(),没有启动多线程
/* my1.run();
my2.run();*/
//调用start(),启动多线程
my1.start();
my2.start();
}
}
1.4 设置和获取线程名称
package mythread;
public class MyThreadDemo {
public static void main(String[] args) {
MyThread my1= new MyThread();
MyThread my2= new MyThread();
//第一种设置和获取线程名称的方法:通过setName()设置,通过getName()返回
my1.setName("test1");
my2.setName("test2");
// 第二种:通过带参构造方法
MyThread my3= new MyThread("test3");
MyThread my4= new MyThread("test4");
my3.start();
my4.start();
//第三种:static Thread currentThread() 返回当前正在执行的线程对象的引用
System.out.println(Thread.currentThread().getName());//输出结果:main
}
}
1.5 线程调度
package mythread;
public class MyThreadDemo {
public static void main(String[] args) {
MyThread my1= new MyThread();
MyThread my2= new MyThread();
/* System.out.println(my1.getPriority());//5
System.out.println(my2.getPriority());//5
System.out.println(Thread.MAX_PRIORITY);//10
System.out.println(Thread.MIN_PRIORITY);//1
System.out.println(Thread.NORM_PRIORITY);//5*/
my1.setName("test1");
my2.setName("test2");
my1.setPriority(1);
my2.setPriority(10);
my1.start();
my2.start();
}
}
1.6 线程控制
package mythread;
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 mythread;
public class ThreadSleepDemo {
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 mythread;
public class ThreadJoin extends Thread{
@Override
public void run() {
for(int i=0;i<100;i++){
System.out.println(getName()+":"+i);
}
}
}
package mythread;
public class ThreadJoinDemo {
public static void main(String[] args) {
ThreadJoin ii1= new ThreadJoin();
ThreadJoin ii2= new ThreadJoin();
ThreadJoin ii3= new ThreadJoin();
ii1.setName("康熙");
ii2.setName("四阿哥");
ii3.setName("八阿哥");
ii1.start();
try {
ii1.join();//等到这个线程死亡
} catch (InterruptedException e) {
e.printStackTrace();
}
ii2.start();
ii3.start();
}
}
package mythread;
/*
* void setDaemon(boolean on):将此线程标记为守护线程,当运行的程序都是守护线程是,Java虚拟机将退出
* */
public class ThreadDaemonTest {
public static void main(String[] args) {
MyThread td1 = new MyThread();
MyThread td2 = new MyThread();
td1.setName("关羽");
td2.setName("张飞");
Thread.currentThread().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);
}
}
}
1.7 线程生命周期
1.8 多线程的实现方式
package mythread;
public class MyRunnable implements Runnable{
@Override
public void run(){
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
package mythread;
public class MyRunnableDemo {
public static void main(String[] args) {
MyRunnable my = new MyRunnable();
Thread t1 = new Thread(my,"高铁");
Thread t2 = new Thread(my,"飞机");
t1.start();
t2.start();
}
}
2.线程同步
2.1 卖票案例
package mythread;
public class SellTicket implements Runnable {
private int tickets = 100;
@Override
public void run(){
while (true) {
if (tickets > 0) {
try{
Thread.sleep(100);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"售卖第"+tickets+"票");
tickets--;
}
}
}
}
package mythread;
public class SellTicketDemo {
public static void main(String[] args) {
SellTicket s = new SellTicket();
Thread t1= new Thread(s,"窗口1");
Thread t2= new Thread(s,"窗口2");
Thread t3= new Thread(s,"窗口3");
t1.start();
t2.start();
t3.start();
}
}
2.2 卖票案例数据安全问题的解决
2.3 同步代码块
优化代码:
package mythread;
public class SellTicket implements Runnable {
private int tickets = 100;
private Object obj = new Object();
@Override
public void run(){
while (true) {
synchronized (obj) {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "售卖第" + tickets + "票");
tickets--;
}
}
}
}
}
2.4 同步方法
同步普通方法格式:
package mythread;
public class SellTicket implements Runnable {
private int tickets = 100;
private int x = 0;
@Override
public void run(){
while (true) {
if(x % 2 ==0){
synchronized (this) {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "售卖第" + tickets + "票");
tickets--;
}
}
}else{
sell();
}
x++;
}
}
public synchronized void sell(){
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "售卖第" + tickets + "票");
tickets--;
}
}
}
同步静态方法格式:
package mythread;
public class SellTicket implements Runnable {
private static int tickets = 100;
private int x = 0;
@Override
public void run(){
while (true) {
if(x % 2 ==0){
synchronized (SellTicket.class) {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "售卖第" + tickets + "票");
tickets--;
}
}
}else{
sell();
}
x++;
}
}
public static synchronized void sell(){
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "售卖第" + tickets + "票");
tickets--;
}
}
}
2.5 线程安全的类
2.6 Lock
package mythread;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SellTicket implements Runnable {
private static int tickets = 100;
private Lock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
try {
lock.lock();
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "售卖第" + tickets + "票");
tickets--;
}
} finally {
lock.unlock();
}
}
}
}
3.生产者和消费者
package mythread;
public class Box {
private int milk;
private boolean state = false;//奶箱的状态
public synchronized void put(int milk){
//如果有牛奶,就等待消费
if(state){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果没有牛奶,就生产牛奶
this.milk=milk;
System.out.println("送奶工将第"+this.milk+"瓶牛奶放入奶箱");
state=true;
notifyAll();
}
public synchronized void get(){
//如果没有牛奶,就等待生产
if(!state){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果有牛奶,就取牛奶
System.out.println("取第"+this.milk+"瓶牛奶");
state=false;
notifyAll();
}
}
package mythread;
public class Producer implements Runnable{
private Box box;
public Producer(Box box){
this.box=box;
}
@Override
public void run(){
for(int i=1;i<5;i++){
box.put(i);
}
}
}
package mythread;
public class Consumer implements Runnable{
private Box box;
public Consumer(Box box){
this.box=box;
}
@Override
public void run(){
while (true){
box.get();
}
}
}
package mythread;
public class BoxDemo {
public static void main(String[] args) {
Box box1= new Box();
Producer p = new Producer(box1);
Consumer s = new Consumer(box1);
Thread t1= new Thread(p);
Thread t2= new Thread(s);
t1.start();
t2.start();
}
}
输出结果:
送奶工将第1瓶牛奶放入奶箱
取第1瓶牛奶
送奶工将第2瓶牛奶放入奶箱
取第2瓶牛奶
送奶工将第3瓶牛奶放入奶箱
取第3瓶牛奶
送奶工将第4瓶牛奶放入奶箱
取第4瓶牛奶