第十八次课
一.
package com.hpe.demo;
import java.time.LocalDateTime;
// 单 线程 ! 主线程一条线,就可以把程序串起来。
public class Demo1 {
public static void main(String[] args) {
test1("张三");
// 当前时间
LocalDateTime.now(); //
int num = 10;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 程序需要等待一下。 num修改为100的时候。
test1("李四");
}
public static void test1(String name) {
System.out.println("test1" + name);
for (int i = 0; i < 30; i++) {
System.out.println(i);
}
test2(name);
}
public static void test2(String name) {
for (int i = 0; i < 30; i++) {
System.out.println(i);
}
System.out.println("test2" + name);
}
}
二.package com.hpe.demo;
/**
- 继承Thread类,完成多线程的示例
- 步骤:
- 1、继承Thread类。创建一个Thread的子类。
- 2、重写run方法
- 3、创建对象(实例)
- 4、调用线程的start()方法。
- @author Administrator
*/
class TestThread extends Thread{
// run方法。多次执行或同时执行的业务,放到run方法体中。-----》 线程体。
@Override
public void run() {
System.out.println(“线程体”+ Thread.currentThread().getName());
}
}
public class Demo2{
public static void main(String[] args) {
// 创建多线程对象
TestThread testThread1 = new TestThread();
TestThread testThread2 = new TestThread();
TestThread testThread3 = new TestThread();
TestThread testThread4 = new TestThread();
// 调用线程方法,start() ===》 启动线程。 (调用了run方法)
testThread1.start(); // 一个线程只能调用一次。
testThread2.start(); // 一个线程只能调用一次。
testThread3.start(); // 一个线程只能调用一次。
testThread4.start(); // 一个线程只能调用一次。
}
}
三.
package com.hpe.demo;
public class Demo3 {
public static void main(String[] args) {
NumThread n1 = new NumThread();
n1.setName(“n1”);
NumThread n2 = new NumThread();
n2.setName(“n2”);
// 同时执行 n1 和n2.
n1.start();
n2.start();
NumThread n3 = new NumThread();
n3.setName("n3");
n3.start();
// 主线程
System.out.println(Thread.currentThread().getName());
}
}
/**
- 多线程输出1 ---- 100
- @author Administrator
*/
class NumThread extends Thread{
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(i == 50) {
// 让此线程,交出控制台打印的控制权。
// n1 49 50 51 // 线程阻塞
// n2 46 47 48 49 50
}
if(i == 90) {
Thread.currentThread().stop();
}
}
}
}
四.
package com.hpe.demo;
/**
- 在线程执行过程中,线程让步 yield方法。
- 1、start ()
- 2、run();
- 3、stop();
- 4、getName
- 5\seetName
- 6、currentThread 获取当前线程。
- 7、sleep 睡棉
- 8\isAlive () 判断当前线程是否活着。
- 9、getPriority 获取优先级 。默认 5 最小是1 最大是 10.
- 10、setPrority 设置优先级。
- 11\ yield方法,释放当前cpu的执行权。
- 12 join 在当前线程中调用另外一个线程中的方法。 当前线程停止(阻塞),直到另一个线程执行完成。才开始当前线程。
- 13 线程通信:
-
等待
-
唤醒
- @author Administrator
*/
public class Demo4 {
public static void main(String[] args) {
NumsThread n1 = new NumsThread();
n1.setName(“n1”);
NumsThread n2 = new NumsThread();
n2.setName(“n2”);
// 同时执行 n1 和n2.
n1.start();
n2.start();
NumsThread n3 = new NumsThread();
n3.setName("n3");
// 优先级最高
n3.setPriority(Thread.MAX_PRIORITY);
n3.start();
// 主线程
System.out.println(Thread.currentThread().getName());
System.out.println(Thread.currentThread().isAlive());
}
}
/**
- 多线程输出1 ---- 100
- @author Administrator
*/
class NumsThread extends Thread{
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i + " 优先级:" + Thread.currentThread().getPriority());
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
/*
* if(i == 40) { Thread.currentThread().setPriority(6); }
*/
if(i == 50) {
// 让此线程,交出控制台打印的控制权。
// n1 49 50 51 // 线程阻塞
// n2 46 47 48 49 50
// 交出控制
Thread.currentThread().yield();
}
boolean b = Thread.currentThread().isAlive();
System.out.println("当前线程是否存活:" + b);
}
}
}
另一个文件
一.
package com.hpe.demo4;
/**
- 用继承实现售票
- @author Administrator
*/
public class Demo1 {
public static void main(String[] args) {
window w1 = new window();
w1.setName(“w1”);
window w2 = new window();
w2.setName(“w2”);
window w3 = new window();
w3.setName(“w3”);
w1.start();
w2.start();
w3.start();
}
}
/**
-
模拟窗口
*/
class window extends Thread{// 总票数 三个线程公有变量 static
static int ticker = 100;/**
- 添加同步方法解决同步问题。
*/
@Override
public synchronized void run() {
// 取票。
while(ticker > 0) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + “票数:” + ticker – );
}
}
}
- 添加同步方法解决同步问题。
二.
package com.hpe.demo4;
/**
- 实现方式
- Demo1里面,问题:线程安全的安全的问题。 两个窗口同时获取到了票数 99(重票,错票)
- 原因:一个线程操作共享数据中,未执行完成的情况下,另外一个线程参与计算了。导致共享数据安全问题。
- Demo2里面同样也有重票,错票问题。
- @author Administrator
*/
public class Demo2 {
public static void main(String[] args) {
Window1 w = new Window1();
// 三个线程。
Thread t1 = new Thread(w);
Thread t2 = new Thread(w);
Thread t3 = new Thread(w);
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}
//
class Window1 implements Runnable{
int ticker = 100;
@Override
public void run() {
/*
* 解决同步问题。
* 把当前window窗口,this当前的线程。
*/
// synchronized(this) {
// // 取票。
// while(ticker > 0) {
// try {
// Thread.sleep(500);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
//
// System.out.println(Thread.currentThread().getName() + “票数:” + ticker --);
// }
// }
while(true) {
synchronized (this) {
if(ticker > 0) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
//
System.out.println(Thread.currentThread().getName() + "票数:" + ticker --);
}
}
}
}
}
三.
package com.hpe.demo4;
/**
- 用继承实现售票
- @author Administrator
*/
public class Demo3 {
public static void main(String[] args) {
window2 w1 = new window2();
w1.setName(“w1”);
window2 w2 = new window2();
w2.setName(“w2”);
window2 w3 = new window2();
w3.setName(“w3”);
w1.start();
w2.start();
w3.start();
}
}
/**
-
模拟窗口
*/
class window2 extends Thread{// 总票数 三个线程公有变量 static
static int ticker = 100;// 模拟一个监控对象
static Object o = new Object();/**
-
添加同步方法解决同步问题。
*/
@Override
public void run() {
//代码同步: this代表三个线程对象。不能使用this作为同步的监视器。
synchronized (o) {
// 取票。
while(ticker > 0) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + “票数:” + ticker – );
}}
}
}
-
四.
package com.hpe.demo4;
/**
- 同步锁的语法演示
- 多线程里面的 ,安全问题,同步机制。
- @author Administrator
*/
public class TestSynchronized {
private int a = 1;
{
// 代码块
}
static {
// 初始工作
}
// 同步方法
public synchronized void test1() {
for (int i = 0; i < 100; i++) {
System.out.println("i = " + i);
}
}
public void test() {
// 同步代码
synchronized (this) {
for (int i = 0; i < 100; i++) {
System.out.println("i = " + i);
}
}
}
}
另一个文件
一
package com.hpe.lianxi;
/**
- 练习:两个线程,打印奇偶数。
- @author Administrator
*/
public class Demo1 {
public static void main(String[] args) {
Test1 t1 = new Test1();
Test2 t2 =new Test2();
t1.setName(“偶数”);
t2.setName(“奇数”);
t1.start();
t2.start();
}
}
class Test1 extends Thread{
@Override
public void run() {
for (int i = 0; i <=100; i++) {
if(i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + “i =” + i);
}
}
}
}
class Test2 extends Thread{
@Override
public void run() {
for (int i = 0; i <=100; i++) {
if(i % 2 != 0) {
System.out.println(Thread.currentThread().getName() + “i =” + i);
}
}
}
}
另一个文件
一.
package com.hpe.runnable;
/**
- 创建多线程的另一个方式: 实现Runnable接口。
- 优点:
- 1、避免单继承 的局限性
- 2、更适合多个线程操作同一个资源的情况。
- @author Administrator
*/
public class Demo1 {
public static void main(String[] args) {
// 使用Thread类的构造函数,创建一个线程。
NumRunable numr1 = new NumRunable();
// 把runnable的子类,传递给Thread类。创建一个线程。
Thread t1 = new Thread(numr1);
Thread t2 = new Thread(numr1);
Thread t3 = new Thread(numr1);
Thread t4 = new Thread(numr1);
// start开始线程。
t1.start();
t2.start();
t3.start();
t4.start();
}
}
//多线程类
class NumRunable implements Runnable{
// 线程业务部分。
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
if(i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + “:” + i);
}
}
}
}