本章概述:
一、api
1、JoinDemo
package com.tensent.class4.api;
public class JoinDemo {
public static void main(String[] args) {
RunDemo runDemo = new RunDemo();
Thread thread = new Thread(runDemo);
thread.start();
for (int i = 0; i < 10; i++) {
if(i == 3){
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "------------" + i);
}
}
}
2、RunDemo
package com.tensent.class4.api;
public class RunDemo implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "------------" + i);
}
}
}
3、SleepDemo
package com.tensent.class4.api;
public class SleepDemo {
public static void main(String[] args) {
RunDemo runDemo = new RunDemo();
Thread thread = new Thread(runDemo);
thread.start();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "------------" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
4、StopDemo
package com.tensent.class4.api;
public class StopDemo {
public static void main(String[] args) {
RunDemo runDemo = new RunDemo();
Thread thread = new Thread(runDemo);
thread.start();
for (int i = 0; i < 100; i++) {
if(i == 2){
thread.stop();
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "------------" + i);
}
}
}
5、ThreadApiDemo
package com.tensent.class4.api;
public class ThreadApiDemo {
public static void main(String[] args) {
//获取当前线程的实例
Thread thread = Thread.currentThread();
//获取当前线程的名称
System.out.println(thread.getName());
//获取线程的优先级,一般情况优先级是0-10之间的整数,默认优先级是5,特殊情况下也可以是0-100之间的整数。
/*
* 作用:
* 数值越大代表优先级越高,但是优先级越高并不一定意味着它会被先执行,而是说优先级高的会执行的效率更大一些,仅此而已。
*/
System.out.println(thread.getPriority());
}
}
6、YieldDemo
package com.tensent.class4.api;
public class YieldDemo {
public static void main(String[] args) {
RunDemo runDemo = new RunDemo();
Thread thread = new Thread(runDemo);
thread.start();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "------------" + i);
if(i == 6){
//线程礼让一次,进入就绪状态,如果就绪队列中没有其他线程或者其他线程没有它自己抢占CPU资源快的话,那么它自己会快读的抢占CPU资源进行运行状态。
Thread.yield();
}
}
}
}
二、proxy
1、JiaShi
package com.tensent.class4.proxy;
public class JiaShi implements KindWomen {
@Override
public void makeEyesWithMen() {
System.out.println("贾氏抛媚眼... ...");
}
@Override
public void playWithMen() {
System.out.println("贾氏... ...");
}
}
2、KindWomen
package com.tensent.class4.proxy;
public interface KindWomen {
/*
* 抛媚眼
*/
public void makeEyesWithMen();
public void playWithMen();
}
3、PanJinLian
package com.tensent.class4.proxy;
public class PanJinLian implements KindWomen {
@Override
public void makeEyesWithMen() {
System.out.println("潘金莲抛媚眼... ..");
}
@Override
public void playWithMen() {
System.out.println("潘金莲... ...");
}
}
4、WangPo
package com.tensent.class4.proxy;
public class WangPo implements KindWomen {
private KindWomen kindWomen;
public WangPo(){
this.kindWomen = new PanJinLian();
}
public WangPo(KindWomen kindWomen){
this.kindWomen = kindWomen;
}
@Override
public void makeEyesWithMen() {
this.kindWomen.makeEyesWithMen();
}
@Override
public void playWithMen() {
this.kindWomen.playWithMen();
}
}
5、XiMenQing
package com.tensent.class4.proxy;
public class XiMenQing {
public static void main(String[] args) {
// WangPo wangPo = new WangPo();
// wangPo.makeEyesWithMen();
// wangPo.playWithMen();
JiaShi jiaShi = new JiaShi();
WangPo wangPo = new WangPo(jiaShi);
wangPo.makeEyesWithMen();
wangPo.playWithMen();
}
}
三、ThreadDemo
1、ThreadDemo
/**
* 实现多线程的两种方式:
* 第一种实现方式:继承Thread类
* 1、需要继承Thread类
* 2、必须要重写run方法,指的是核心执行的逻辑
* 3、线程在启动的时候,不要直接调用run方法,而是要通过start()来进行调用
* 4、每次运行相同的代码,出来的结果可能不一样,原因在于多线程谁先抢占资源无法进行人为控制
* 第二种实现方式:使用了代理设计模式
* 1、实现Runnable接口
* 2、重写run方法
* 3、创建Thread对象,将刚刚创建好的runnable的子类实现作为thread的构造参数
* 4、通过thread.start()进行启动
* 两种实现方式哪种用的比较多
* 推荐使用第二种方式,
* 1、java是单继承,将继承关系留给最需要的类
* 2、使用runnable接口之后不需要给共享变量添加static关键字,每次创建一个对象,作为共享对象即可
* 线程的生命周期:
* 1、新生状态(新建状态):
* 当创建好当前线程对象之后,没有启动之前(调用start方法之前)
* ThreadDemo thread = new ThreadDemo()
* RunnableDemo run = new RunnableDemo()
* 2、就绪状态:准备开始执行,并没有执行,表示调用start方法之后
* 当对应的线程创建完成,且调用start方法之后,所有的线程会添加到一个就绪队列中,所有的线程同时去抢占cpu的资源
* 3、运行状态:当当前进程获取到cpu资源之后,就绪队列中的所有线程会去抢占cpu的资源,谁先抢占到谁先执行,在执行的过程中就叫做运行状态
* 抢占到cpu资源,执行代码逻辑开始
* 4、死亡状态:当运行中的线程正常执行完所有的代码逻辑或者因为异常情况导致程序结束叫做死亡状态
* 进入的方式:
* 1、正常运行完成且结束
* 2、人为中断执行,比如使用stop方法
* 3、程序抛出未捕获的异常
* 5、阻塞状态:在程序运行过程中,发生某些异常情况,导致当前线程无法再顺利执行下去,此时会进入阻塞状态,进入阻塞状态的原因消除之后,
* 所有的阻塞队列会再次进入到就绪状态中,随机抢占cpu的资源,等待执行
* 进入的方式:
* sleep方法
* 等待io资源
* join方法(代码中执行的逻辑)
*
* 注意:
* 在多线程的时候,可以实现唤醒和等待的过程,但是唤醒和等待操作的对应不是thread类
* 而是我们设置的共享对象或者共享变量
* 多线程并发访问的时候回出现数据安全问题:
* 解决方式:
* 1、同步代码块
* synchronized(共享资源、共享对象,需要是object的子类){具体执行的代码块}
* 2、同步方法
* 将核心的代码逻辑定义成一个方法,使用synchronized关键字进行修饰,此时不需要指定共享对象
*
*/
public class ThreadDemo {
public static void main(String[] args) {
/*
一个java程序运行的步骤:
1、编写java源文件,源程序;
2、使用javac命令编译.java文件,生成对应的.class字节码文件
3、使用java命令解释执行.class文件中存在的类
*/
for(int i = 0; ;i++){
System.out.println("hello!");
}
}
}
四、ticket
1、RunnableTicket
package com.tensent.class4.ticket;
/**
* 出现的问题:
* 1、卖票的次序是混乱的;
* 2、每个窗口不能平均的卖票,分配不均,有些窗口卖了很多票,有些窗口一张票都没卖。这个不符合显示情况。
*
*/
public class RunnableTicket implements Runnable {
//资源(火车票)
private int ticket = 10;
@Override
public void run() {
for(int i =0; i <100;i++){
if(ticket > 0){
System.out.println(Thread.currentThread().getName() + "----------正在卖第" + (ticket--) +"张票!");
}
}
}
public static void main(String[] args) {
RunnableTicket runnableTicket = new RunnableTicket();
Thread t1 = new Thread(runnableTicket,"1号窗口");
Thread t2 = new Thread(runnableTicket,"2号窗口");
Thread t3 = new Thread(runnableTicket,"3号窗口");
Thread t4 = new Thread(runnableTicket,"4号窗口");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
2、RunnableTicket2
package com.tensent.class4.ticket;
/**
* 出现的问题:
* 1、卖票的次序是混乱的;
* 2、每个窗口不能平均的卖票,分配不均,有些窗口卖了很多票,有些窗口一张票都没卖。这个不符合显示情况。
*/
public class RunnableTicket2 implements Runnable {
//资源(火车票)
private Integer ticket = 10;
// String str = "";
@Override
public void run() {
//定义一个共同的锁
/*
当多个线程共同访问同一个资源的时候,会出现线程安全问题,此时解决办法之一是加锁,
在java中要求锁是对象类型,任何对象都是可以的,但是需要保证多个线程访问的是同一把锁。
程序中锁的名称特别的锁:
1、锁旗标;
2、同步监视器;
3、同步锁;
4、互斥锁;
5、对象锁;
6、锁
... ...
*/
// String str = "";
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (ticket) {
// synchronized (this){
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "----------正在卖第" + (ticket--) + "张票!");
}
}
}
}
public static void main(String[] args) {
RunnableTicket2 runnableTicket = new RunnableTicket2();
Thread t1 = new Thread(runnableTicket, "1号窗口");
Thread t2 = new Thread(runnableTicket, "2号窗口");
Thread t3 = new Thread(runnableTicket, "3号窗口");
Thread t4 = new Thread(runnableTicket, "4号窗口");
t1.start();
t2.start();
t3.start();
t4.start();
}
3、RunnableTicket3
/**
* <p>
* 出现的问题:
* 1、卖票的次序是混乱的;
* 2、每个窗口不能平均的卖票,分配不均,有些窗口卖了很多票,有些窗口一张票都没卖。这个不符合显示情况。
*/
public class RunnableTicket3 implements Runnable {
//资源(火车票)
private int ticket = 10;
@Override
public void run() {
//定义一个共同的锁
/*
当多个线程共同访问同一个资源的时候,会出现线程安全问题,此时解决办法之一是加锁,
在java中要求锁是对象类型,任何对象都是可以的,但是需要保证多个线程访问的是同一把锁。
程序中锁的名称特别的锁:
1、锁旗标;
2、同步监视器;
3、同步锁;
4、互斥锁;
5、对象锁;
6、锁
... ...
*/
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.sale();
}
}
public synchronized void sale() {
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "----------正在卖第" + (ticket--) + "张票!");
}
}
public static void main(String[] args) {
RunnableTicket3 runnableTicket = new RunnableTicket3();
Thread t1 = new Thread(runnableTicket, "1号窗口");
Thread t2 = new Thread(runnableTicket, "2号窗口");
Thread t3 = new Thread(runnableTicket, "3号窗口");
Thread t4 = new Thread(runnableTicket, "4号窗口");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
4、ThreadTicket
package com.tensent.class4.ticket;
* 模拟4个窗口卖共同的10张火车票
*
* 出现的问题:
* 1、不是在共享10张票的资源,而是各个窗口在卖自己的10张票,出现这种情况的原因每次都new的新的线程,此时ticket变量是和对象相关的,所以对应的就有了4个10张票出现;
* 2、卖票的次序是有问题的。
*
*/
public class ThreadTicket extends Thread {
//资源(火车票)
private static int ticket = 10;
public ThreadTicket(String threadName){
super(threadName);
}
@Override
public void run() {
for(int i =0; i <100;i++){
if(ticket > 0){
System.out.println(Thread.currentThread().getName() + "----------正在卖第" + (ticket--) +"张票!");
}
}
}
public static void main(String[] args) {
ThreadTicket t1 = new ThreadTicket("1号窗口");
ThreadTicket t2 = new ThreadTicket("2号窗口");
ThreadTicket t3 = new ThreadTicket("3号窗口");
ThreadTicket t4 = new ThreadTicket("4号窗口");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
66package com.tensent.class4.thread;
import com.tensent.class2.ticket.ThreadTicket;
public class RunnableDemo implements Runnable {
@Override
public void run() {
for(int i = 0; i<10;i++){
System.out.println(Thread.currentThread().getName() + "------" + i);
}
}
public static void main(String[] args) {
//创建线程对象
RunnableDemo runnableDemo = new RunnableDemo();
//启动线程---使用java中的设计模式(代理模式)
Thread thread = new Thread(runnableDemo);
thread.start();
for(int i = 0; i<10;i++){
System.out.println(Thread.currentThread().getName() + "------" + i);
}
}
}