设置与获取线程名称
package test;
/**
* 设置与获取线程名称
* @author gaofuzhi
*/
public class MyThreadDemo extends Thread{
public MyThreadDemo(){
super();
}
public MyThreadDemo(String string) {
super(string);
}
@Override
public void run() {
for(int i = 0; i < 100; i++){
System.out.println(getName()+":"+i);
}
}
public static void main(String[] args) {
Thread thread1 = new MyThreadDemo();
thread1.start();
thread1.setName("Tom");
//thread1.start();//java.lang.IllegalThreadStateException
Thread thread2 = new MyThreadDemo("Lily");
thread2.start();
Thread thread3 = new MyThreadDemo();
thread3.start();
MyThreadDemo myThreadDemo = new MyThreadDemo();
System.out.println("重新分配的线程的名字为:"+myThreadDemo.getName());
//重新分配的线程的名字为:Thread-2
System.out.println("main线程的名字为:"+Thread.currentThread().getName());
//main线程的名字为:main
}
}
设置与获取线程优先级
分时调度模型和抢占式调度模型。
分时调度模型,是指让所有的线程轮流获得cpu的使用权,并且平均分配每个线程占用的cpu的时间片。
抢占式调度模型,是指优先让可运行池中优先级高的线程占用cpu,如果可运行池中的线程优先级相同,那么就随机选择一个线程,使其占用CPU。处于运行状态的线程会一直运行,直至它不得不放弃CPU。
Java使用的是抢占式调度模型。
package test;
/**
*设置与获取线程优先级
* @author gaofuzhi
*/
public class MyThreadDemo extends Thread{
public MyThreadDemo(){
super();
}
public MyThreadDemo(String string) {
super(string);
}
@Override
public void run() {
for(int i = 0; i < 100; i++){
System.out.println(getName()+":"+i);
}
}
public static void main(String[] args) {
MyThreadDemo thread1 = new MyThreadDemo("关羽");
thread1.start();
System.out.println("线程1的优先级:"+thread1.getPriority());
MyThreadDemo thread2 = new MyThreadDemo("刘备");
thread2.start();
//thread2.setPriority(0);//java.lang.IllegalArgumentException
thread2.setPriority(10);//优先级高只能代表它抢占上cpu的概率比较大
System.out.println("线程2的优先级:"+thread2.getPriority());
MyThreadDemo thread3 = new MyThreadDemo("张飞");
thread3.start();
System.out.println("线程3的优先级:"+thread3.getPriority());
}
}
yield(同优先级线程礼让)
public static voidyield()
暂停当前正在执行的线程对象,并执行其他线程。
void interrupt() ; 中断线程(状态)。执行run方法,run方法有异常的话抛出异常,但执行异常的后续代码(有循环的话也执行循环);
void stop() ; 直接终止线程。不会执行run方法里面的代码。
已过时。该方法具有固有的不安全性。
多线程实现方式3(在线程池中使用):
实现 java.util.concurrent 接口 Callable。
针对数据重复或不合法出现的情况,通过线程同步解决。
线程同步:
1:线程同步块:
synchronized(锁对象){//锁对象任意但必须唯一
//需共享数据
}
2:线程同步方法:
public synchronized void method(){
//共享数据
}
如果在线程同步块中有线程同步方法,那么锁对象为 this
如果线程同步方法被 static 修饰,则不可能是 this 因为 static 修饰的方法,在this对象没有创建的时候已经加载了(相当于没有发挥作用)。这个时候锁的对象为 类名.class!
在jdk5.0之后,提供了锁接口(Lock)。
java.util.concurrent.locks
接口 Lock
所有已知实现类:
ReentrantLock, ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLock
package test;
/**
* 线程死锁
* @author gaofuzhi
*/
public class MyThreadDemo implements Runnable{
boolean flag = false;
public MyThreadDemo(boolean flag) {
this.flag = flag;
}
//MyThreadDemo mt1 = new MyThreadDemo();
//MyThreadDemo mt2 = new MyThreadDemo();
Object obj1 = new Object();
Object obj2 = new Object();
@Override
public void run() {
if(flag == false){
synchronized (obj1){
System.out.println("筷子1");
synchronized(obj1){
System.out.println("刀1");
}
}
}if(flag == true){
synchronized (obj1){
System.out.println("筷子2");
synchronized(obj1){
System.out.println("刀2");
}
}
}
}
public static void main(String[] args) throws InterruptedException {
MyThreadDemo mtd1 = new MyThreadDemo(false);
MyThreadDemo mtd2 = new MyThreadDemo(true);
Thread thread1 = new Thread(mtd1);
Thread thread2 = new Thread(mtd2);
thread1.start();
thread2.start();
}
}
线程间通信:线程间共享资源。
package threadTest;
/**
* 线程通信 实现方式1
* @author gaofuzhi
*/
public class ThreadCommuniate {
public static void main(String[] args) {
ShareMessage shareMessage = new ShareMessage(); //通过构造方法共享同一个资源对象
Producer producer = new Producer(shareMessage); //生产者构造方法
Consummer consummer = new Consummer(shareMessage); //消费者构造方法
Thread thread1 = new Thread(producer);
Thread thread2 = new Thread(consummer);
thread1.start();
thread2.start();
}
}
class Consummer implements Runnable{ // 消费者类
ShareMessage share;
public Consummer(ShareMessage share){
this.share = share;
}
@Override
public void run() {
System.out.println(share.getName()+"的价格是:"+share.getPrice()+"元");
}
}
class Producer implements Runnable { // 生产者类
ShareMessage share;
public Producer(ShareMessage share){
this.share = share;
}
@Override
public void run() {
share.setName("黄金饼");
share.setPrice(10);
}
}
class ShareMessage{ //资源类
private String name;
private int price;
public ShareMessage() {
super();
}
public ShareMessage(String name, int price) {
super();
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
因为以上run方法中执行的代码较少,所以隐藏了线程安全的问题。经修改,以下代码暴露了线程安全问题。
package threadTest;
/**
* 线程通信 实现方式1
* @author gaofuzhi
*/
public class ThreadCommuniate {
public static void main(String[] args) {
ShareMessage shareMessage = new ShareMessage();
Producer producer = new Producer(shareMessage);
Consummer consummer = new Consummer(shareMessage);
Thread thread1 = new Thread(producer);
Thread thread2 = new Thread(consummer);
thread1.start();
thread2.start();
}
}
class Consummer implements Runnable{
ShareMessage share;
public Consummer(ShareMessage share){
this.share = share;
}
@Override
public void run() {
for(int j = 0;j<1000;j++){
System.out.println(share.getName()+
"的价格是:"+share.getPrice()+"元");
}
}
}
class Producer implements Runnable {
ShareMessage share;
public Producer(ShareMessage share){
this.share = share;
}
@Override
public void run() {
for(int i = 1; i < 1000; i++){
if(i%2==0){
share.setName("黄金饼");
share.setPrice(10);
}else{
share.setName("白银汤");
share.setPrice(8);
}
}
}
}
class ShareMessage{
private String name;
private int price;
public ShareMessage() {
super();
}
public ShareMessage(String name, int price) {
super();
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
分析:
重复数据出现:线程执行速度过快,第二次覆盖了上一次的值。
数据不匹配:线程执行具有随机性。
解决第二个问题方法:线程同步,即上锁。注意:不同种类的线程都必须加锁,且是相同锁(锁对象相同)。
新的需求: 当生产者没有货的时候,消费者等待、并通知生产者生产;当生产者生产好的时候,通知消费者消费、等待消费者消费;如此循环往复。
基于此种思想:Object 类提供了如下方法,实现以上需求。
疑问:既然针对的是线程的方法,为什么不定义在Thread类中,反而定义在Object类中呢?
原因:这些方法的调用对象为锁对象,而锁对象( synchronized(锁对象) { } )可以为任何对象,所以定义在所有类的超类Object中最恰当。
package threadTest;
/**
* 线程等待唤醒机制(按实际情况生产)
* @author gaofuzhi
*/
public class ThreadCommuniate {
public static void main(String[] args) {
ShareMessage shareMessage = new ShareMessage();
Producer producer = new Producer(shareMessage);
Consummer consummer = new Consummer(shareMessage);
Thread thread1 = new Thread(producer);
Thread thread2 = new Thread(consummer);
thread1.start();
thread2.start();
}
}
class Consummer implements Runnable{
ShareMessage share;
public Consummer(ShareMessage share){
this.share = share;
}
@Override
public void run() {
for (int i = 1; i < 50; i++) {
synchronized(share){
if(share.getMount()>0){
System.out.println(share.getName()+
"被我以"+share.getPrice()+"元买了,请再生产!");
share.setMount(share.getMount()-1);
share.notify();
}else{
try {
share.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
class Producer implements Runnable {
ShareMessage share;
public Producer(ShareMessage share){
this.share = share;
}
@Override
public void run() {
for (int j = 1; j < 50; j++) {
synchronized(share){
if(share.getMount()<1){
share.setName("黄金饼");
share.setPrice(10);
share.setMount(share.getMount()+1);
share.notify();
}else{
try {
share.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
class ShareMessage{
private String name;
private int price;
private int mount;
public int getMount() {
return mount;
}
public void setMount(int mount) {
this.mount = mount;
}
public ShareMessage() {
super();
}
public ShareMessage(String name, int price) {
super();
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
线程池
package threadTest;
/**
* 线程池
* @author gaofuzhi
*/
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPool implements Runnable {
public static void main(String[] args) {
//创建线程池对象
ExecutorService pool = Executors.newFixedThreadPool(2);
//添加线程
pool.submit(new ThreadPool());
pool.submit(new ThreadPool());
//释放资源
pool.shutdown();
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
多线程匿名内部类和接口
package threadTest;
/**
* 多线程匿名内部类和接口
* @author gaofuzhi
*/
public class HideThread {
public static void main(String[] args) {
//多线程匿名内部类
new Thread(){
@Override
public void run(){
for(int i = 0;i < 9;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}.start();
new Thread(){
@Override
public void run(){
for(int i = 0;i < 9;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}.start();
//多线程匿名接口
new Thread(new Runnable(){
@Override
public void run() {
for (int i = 0; i < 11; i++) {
System.out.println("tr1:"+i);
}
}
}){
// @Override
// public void run() {//有此方法的话,执行此方法,否则执行第一个方法
// for (int i = 0; i < 11; i++) {
// System.out.println("tr2:"+i);
// }
// }
}.start();
}
}