1.方法多参数
语法:
访问修饰符 返回值类型 方法名称(数据类型 ... 变量名) {
方法体
return 返回值;
}
注意点: 多参数本质就是一个数组
2.Properties
public Object setProperty(String key,String value) ==>设置键值对
public String getProperty(String key) 根据键获取值
public Set stringPropertyNames() 返回此属性列表中的键集
public void load(InputStream inStream) 从输入流中读取属性列表
public void store(OutputStream out,String comments) 将Properties对象中数据写入到文件中
3.加载配置文件的工具类
4.多线程
并发:在同一时间段 执行两个或者多个操作 单核cpu交替执行(例子:一人吃两个包子)
并行:在同一时刻 执行两个或者多个操作 多核cpu同时执行(例子:两人吃两个包子)
进程:运行在内存中程序就是进程
线程:通向cpu的执行的路径就是线程
第一种创建方式:
A.继承Thread
B.重写run方法
C.实例化线程对象
D.调用开启线程的方法 start()
常用的方法:
A.获取线程名称
a. public final String getName()
b.public static Thread currentThread() 获取当前线程
B.设置线程名称
a.public Thread(String name)
b.public final void setName(String name)
二、线程中常用方法
2.1 线程休眠
| 方法名称 | 方法描述 |
|---|---|
| public static void sleep(long millis) | 在指定的毫秒数内让当前正在执行的线程休眠 |
代码-线程类
package com.qf.test02;
public class MyThread extends Thread {
@Override
public void run() {
for (int i=15;i>0;i--) {
System.out.println("还剩下"+i+"秒");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
代码-测试类
package com.qf.test02;
public class Test01 {
public static void main(String[] args) {
//实例化线程类
MyThread th = new MyThread();
th.start();
}
}
2.2 守护线程
1.守护线程:守护其它的线程 守护其它线程执行操作 在java中gc就是守护线程 项目在运行中会产生很多垃圾
这些垃圾都由gc默默在后台进行回收 gc就是一个守护线程
2.守护线程死亡:
A.被守护线程执行完操作
B.被守护线程死亡
3.守护线程一般是守护主线程
| 方法名称 | 方法描述 |
|---|---|
| public final void setDaemon(boolean on) | 将该线程标记为守护线程或用户线程 |
| public final boolean isDaemon() | 测试该线程是否为守护线程 |
代码-线程类
package com.qf.test03;
import java.io.*;
public class MyThread extends Thread {
@Override
public void run() {
//睡五秒钟
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
//实例化流对象
OutputStream os = new FileOutputStream("5.txt");
os.write(97);
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
代码-测试类
package com.qf.test03;
public class Test01 {
public static void main(String[] args) {
//实例化线程对象
MyThread th = new MyThread();
//将该线程设置为守护线程
th.setDaemon(true);
//获取是否为守护线程
System.out.println(th.isDaemon());
//开启线程
th.start();
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
2.3 线程的优先级
注意点:
A.线程的优先级范围是1-10 线程优先级默认值是5
2.3.1 常量| 常量的名称 | 常量说明 |
|---|---|
| public static final int MAX_PRIORITY | 线程可以具有的最高优先级 |
| public static final int MIN_PRIORITY | 线程可以具有的最低优先级 |
| public static final int NORM_PRIORITY | 分配给线程的默认优先级 |
注意点: 线程优先级越高 表示获取cpu的执行权越大 优先级越高 执行的概率越大
| 方法名称 | 方法描述 |
|---|---|
| public final void setPriority(int newPriority) | 更改线程的优先级 |
| public final int getPriority() | 获取线程优先级 |
代码-线程类
package com.qf.test04;
public class MyThread extends Thread {
@Override
public void run() {
for (int i=1;i<=100;i++){
System.out.println(getName()+"t"+i);
}
}
}
代码-测试类
package com.qf.test04;
public class Test01 {
public static void main(String[] args) {
//实例化第一个线程对象
MyThread th01 = new MyThread();
th01.setPriority(5);
th01.start();
//实例化第二个线程对象
MyThread th02 = new MyThread();
th02.setPriority(3);
th02.start();
//实例化第三个线程对象
MyThread th03 = new MyThread();
th03.setPriority(10);
th03.start();
}
}
2.4 线程第二种创建方式
步骤
A.定义一个类 实现 Runnable接口 B.实现run()方法 C.实例化线程对象Thread 构造方法中传递Runnable的实现类 D.调用线程开启方法 start()
代码-线程类
package com.qf.test05;
public class MyRunnable implements Runnable {
@Override
public void run() {
for (int i=0;i<=100;i++) {
System.out.println(Thread.currentThread().getName()+"t"+i);
}
}
}
代码-测试类
package com.qf.test05;
public class Test01 {
public static void main(String[] args) {
//实例化Runnable实现类
MyRunnable ru = new MyRunnable();
//实例化线程对象
Thread th = new Thread(ru);
//开启线程
th.start();
//实例化Runnable实现类
MyRunnable ru1 = new MyRunnable();
//实例化线程对象
Thread th1 = new Thread(ru1);
//开启线程
th1.start();
}
}
2.5 使用匿名内部类创建线程
package com.qf.test06;
public class Test01 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}).start();
new Thread(){
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}.start();
}
}
三、线程通信
3.1 案例-需求
3.2 分析
A.三个窗口 可以使用三个线程 B.需要数据共享 实现Runnable接口 C.定义一个变量来记录100张票 D.一直买票 死循环 while(true)3.3 代码
线程类
package com.qf.test07;
public class MyRunnable implements Runnable {
//定义变量来记录100张票
private int count = 100;
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//一直买票
while (true) {
//有票才能售卖
if (count > 0) {
System.out.println(Thread.currentThread().getName() + "在出售第" + count + "票");
//票数需要递减
count--;
}
}
}
}
测试类
package com.qf.test07;
public class Test01 {
public static void main(String[] args) {
//实例化MyRunnable
MyRunnable run = new MyRunnable();
//实例化第一个线程对象
Thread th01 = new Thread(run);
th01.start();
//实例化第二个线程对象
Thread th02 = new Thread(run);
th02.start();
//实例化第三个线程对象
Thread th03 = new Thread(run);
th03.start();
}
}
3.4 产生问题的原因
3.5 第一种解决方案-使用同步代码块
1.语法:
synchronized(锁的对象) {
可能产生数据共享安全问题代码
}
2.说明:
A.锁的对象可以是任意的对象
B.所有的线程必须操作的是同一个锁对象
3.作用:
解决多线程数据安全的问题
代码
package com.qf.test07;
public class MyRunnable implements Runnable {
private int count = 100;
//定义一个锁的对象
private Object obj = new Object();
@Override
public void run() {
while (true) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj) {
if (count > 0) {
System.out.println(Thread.currentThread().getName() + "在出售第" + count + "票");
count--;
}
}
}
}
}
3.6 解决问题原因
3.7 第二种解决方案-同步方法
1.语法:
访问修饰符 synchronized 返回值类型 方法的名称(参数列表) {
方法体;
return 返回值
}
2.说明:
A.synchronized 可以修饰普通成员方法 也可以修饰静态方法
3.注意点
A.普通成员方法锁的对象是当前对象this
B.静态方法锁的对象是当前对象的class对象
代码
package com.qf.test07;
public class MyRunnable implements Runnable {
private static int count = 100;
@Override
public void run() {
while (true) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
//showInfo();
//showInfo();
synchronized (MyRunnable.class){
if (count > 0) {
System.out.println(Thread.currentThread().getName() + "在出售第" + count + "票");
count--;
}
}
}
}
}
3.8 第三种解决方案-Lock
1.Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构 2.实现类:ReentrantLock 3.方法
| 方法名称 | 方法描述 |
|---|---|
| void lock() | 获取锁对象 |
| void unlock() | 释放锁 |
代码
package com.qf.test07;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MyRunnable implements Runnable {
private static int count = 100;
//实例化锁对象
private Lock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
//获取锁对象
lock.lock();
try {
Thread.sleep(50);
if (count > 0) {
System.out.println(Thread.currentThread().getName() + "在出售第" + count + "票");
count--;
}
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
//释放锁对
lock.unlock();
}
}
}
}
四、死锁
1.概念:死锁 A占用B锁的锁对象 B占用A锁对象 互不相让 两个线程处于等待状态 这样就出现了死锁 2.生活例子: 阿飞与阿超同一个宿舍 宿舍中只有一双拖鞋 两个人都要出去买东西 阿飞抢到左拖鞋 阿超强到右拖鞋 两人互不谦让 两人都出不去 死锁
代码-鞋子类
package com.qf.test08;
public class Shoe {
//左拖鞋
public static final String LEFT="LEFT";
//右拖鞋
public static final String RGIGHT="RGIGHT";
}
代码-MyRunnable01
package com.qf.test08;
public class MyRunnable01 implements Runnable{
@Override
public void run() {
synchronized (Shoe.LEFT){
System.out.println("阿飞获取左拖鞋");
synchronized (Shoe.RGIGHT) {
System.out.println("阿飞获取右拖鞋");
}
}
}
}
代码-MyRunnable02
package com.qf.test08;
public class MyRunnable02 implements Runnable {
@Override
public void run() {
synchronized (Shoe.RGIGHT){
System.out.println("阿超获取右拖鞋");
synchronized (Shoe.LEFT){
System.out.println("阿超获取左拖鞋");
}
}
}
}
代码-测试类
package com.qf.test08;
public class Test01 {
public static void main(String[] args) {
MyRunnable01 run01 = new MyRunnable01();
//实例化线程对象
Thread th01 = new Thread(run01);
//开启线程
th01.start();
MyRunnable02 run02 = new MyRunnable02();
//实例化线程对象
Thread th02 =new Thread(run02);
th02.start();
}
}
五、线程中常用方法
| 方法名称 | 方法描述 |
|---|---|
| public final void stop() | 终止线程(立刻线程中操作) |
| public static void yield() | 暂停当前正在执行的线程对象,并执行其他线程(礼让) |
| public final void join() | 等待该线程终止(这个方法必须在线程开启之后调用) |
代码-线程类
package com.qf.test09;
public class MyThread extends Thread {
@Override
public void run() {
for (int i=1;i<=10;i++){
if (i==5) {
// stop();
interrupt();
}
System.out.println(i);
}
}
}
代码-测试类
package com.qf.test09;
public class Test01 {
public static void main(String[] args) {
MyThread th = new MyThread();
th.start();
}
}
5.2 yield() 方法演示
代码-线程类
package com.qf.test10;
public class MyThread extends Thread {
@Override
public void run() {
for (int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+"t"+i);
}
}
}
代码-测试类
package com.qf.test10;
public class Test01 {
public static void main(String[] args) {
//实例化线程对象
MyThread th01 = new MyThread();
//礼让
th01.yield();
//开启线程
th01.start();
//实例化线程对象
MyThread th02 = new MyThread();
th02.start();
}
}
5.3 join() 方法演示
代码-线程类
package com.qf.test11;
public class MyThread extends Thread {
@Override
public void run() {
for (int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+"t"+i);
}
}
}
代码-测试类
package com.qf.test11;
public class Test01 {
public static void main(String[] args) throws InterruptedException {
//实例化线程对象
MyThread th01 = new MyThread();
//开启线程
th01.start();
th01.join();
//实例化线程对象
MyThread th02 = new MyThread();
th02.start();
}
}
六、Object提供操作线程的方法
| 方法的名称 | 方法的描述 |
|---|---|
| public final void wait(long timeout) | 计时等待 |
| public final void wait() | 无线等待 |
| public final void notify() | 唤醒在此对象监视器上等待的单个线程(唤醒一个) |
| public final void notifyAll() | 唤醒在此对象监视器上等待的所有线程 |
代码
package com.qf.test12;
public class Test01 {
public static void main(String[] args) {
//定义一个锁对象
Object obj = new Object();
//李焕荣线程
new Thread(){
@Override
public void run() {
synchronized (obj){
System.out.println("我需要一个包子");
//无线等待
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("正在吃包子........");
}
}
}.start();
//老板线程
new Thread(){
@Override
public void run() {
synchronized (obj){
//花两秒钟做一个包子
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("已经做好了一个包子");
//通知李焕荣吃包子
obj.notify();
}
}
}.start();
}
}
八、多线程中生产者与消费者模式
step01 需求-分析
step01-生产者线程
package com.qf.test13;
public class MyThread01 extends Thread {
private BaoZi baoZi;
public MyThread01(BaoZi baoZi){
this.baoZi=baoZi;
}
@Override
public void run() {
//一直生产包子
while (true){
synchronized (baoZi) {
//需要无线等待
if (baoZi.flag) {
try {
baoZi.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//生产一个包子
baoZi.pi="薄皮";
baoZi.xian="韭菜鸡蛋";
System.out.println("生产一个"+baoZi.pi+"t"+baoZi.xian+"包子");
//将标记设置为true
baoZi.flag= true;
//通知消费者进行消费
baoZi.notify();
}
}
}
}
step02-消费者线程
package com.qf.test13;
public class MyThread02 extends Thread {
private BaoZi baoZi;
public MyThread02(BaoZi baoZi) {
this.baoZi=baoZi;
}
@Override
public void run() {
//一直消费包子
while (true){
synchronized (baoZi){
if (!baoZi.flag){
try {
baoZi.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//消费包子
System.out.println("消费了一个"+baoZi.pi+"t"+baoZi.xian+"的包子");
baoZi.xian=null;
baoZi.pi=null;
//将标记设置为false
baoZi.flag=false;
//通知生产者生成包子
baoZi.notify();
}
}
}
}
step03 包子类
package com.qf.test13;
public class BaoZi {
public String pi;
public String xian;
public boolean flag = false; // 表示没有包子
}
step04-测试类
package com.qf.test13;
public class Test01 {
public static void main(String[] args) {
//实例化包子对象
BaoZi baoZi = new BaoZi();
//实例化生成者线程
new MyThread01(baoZi).start();
//实例化消费者线程
new MyThread02(baoZi).start();
}
}



