模拟线程通信之生产者和消费者
package _01_Product_Consumer;
public class app {
public static void main(String[] args) {
ShareResource share = new ShareResource();
new Thread(new Product(share)).start();
new Thread(new Consumer(share)).start();
}
}
package _01_Product_Consumer;
public class Consumer implements Runnable {
private ShareResource share = null;
public Consumer(ShareResource share){
this.share = share;
}
@Override
public void run() {
for(int i=0;i<1000;i++){
share.popup();
}
}
}
package _01_Product_Consumer;
public class Product implements Runnable{
private ShareResource share = null;
public Product(ShareResource share){
this.share = share;
}
@Override
public void run() {
for(int i=0;i<1000;i++){
if(i % 2 != 0){
share.push("著姐","女");
}else{
share.push("春哥" ,"男");
}
}
}
}
package _01_Product_Consumer;
public class ShareResource {
private String name;
private String sex;
public void push(String name,String sex){
this.name = name;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.sex = sex;
}
public void popup() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(name+"----"+sex);
}
}
上述代码只是简单的模拟了下,如果通过Thread.sleep(100)方法,就会放大线程不安全的问题,男女性别不符合问题.
可以使用synchronized来修饰方法 达到同步,但是问题还是存在------生产者生产一个,消费者消费一个,应该是这样的情况
解决这种情况的话使用wait和notify
package _03_wait;
public class ShareResouce {
private String name;
private String sex;
private boolean flag = true;
synchronized public void push(String name,String sex) {
while(!flag){
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.name = name ;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.sex = sex;
flag = false;
this.notify();
}
synchronized public void pop() {
while(flag){
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(name+"-----"+sex);
flag = true ;
this.notify();
}
}
还有中方法是使用lock机制
package _04_Lock;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ShareResouce {
private String name;
private String sex;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private boolean isEmpty = true;
synchronized public void push(String name,String sex) {
lock.lock();
try{
while(!isEmpty){
condition.await();
}
this.name = name;
Thread.sleep(10);
this.sex = sex;
isEmpty = false;
condition.signal();
}catch(Exception e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
synchronized public void pop() {
lock.lock();
try{
while(isEmpty){
condition.await();
}
Thread.sleep(100);
System.out.println(name+"-----"+sex);
isEmpty = true;
condition.signal();
}catch(Exception e){
e.printStackTrace();
}finally{
lock.lock();
}
}
}
死锁的问题,就是拿着线程不放,打个不巧当的比方就是,女方说:你先买房我再嫁给你.男方说:你先嫁给我,我再买房.
线程的生命周期
1 NEW 只是new而已
2 RUNNABLE 运行了start方法
3 BLOCKED 在IO中,如果main中存在System.in.read()//接受键盘输入
如果不输入那么main线程一个会在阻塞中
4 WAITING 线程中使用wait方法
5 TIMED_WAITING 就是在使用Thread.sleep()
6 TERMINATED 线程结束.
控制线程
联合线程 A线程需要拿到B线程的执行结果才能继续运行.
package _05_kongzhi_Thread;
class JoinThread extends Thread{
@Override
public void run() {
for(int i=0;i<100;i++){
System.out.println("联合"+i);
}
}
}
public class Lianhe {
public static void main(String[] args) throws Exception {
System.out.println("程序开始");
JoinThread jh = new JoinThread();
for(int i=0;i<50;i++){
System.out.println("main"+i);
if(i == 5){
jh.start();//这里还是cpu调度问题,不会立马执行jh线程的
}
if(i==10){
jh.join();//这里的话为什么会成功,相当于强制挤进来的,我要运行
}
}
System.out.println("程序结束");
}
}
后台线程 JVM的垃圾回收器就是典型的后台线程
package _05_kongzhi_Thread;
class Daemonxx extends Thread{
@Override
public void run() {
for(int i=0;i<1000;i++){
System.out.println("是否是后台线程"+this.isDaemon());
}
}
}
public class DaemonDemo {
public static void main(String[] args) {
System.out.println("main线程是否是主线程"+Thread.currentThread().isDaemon());
Daemonxx xx = new Daemonxx();
xx.setDaemon(true);
xx.start();
for(int i=0;i<10;i++){
System.out.println("main...");
}
}
}
上图是守护线程的执行结果,可以看出主方法结束了还要再执行后台进程,确认是否真的结束了.
线程睡眠 就是sleep()
线程优先级 有几个常量 MAX_PRIORITY10 MIN_PRIORITY1 NORM_PRIORITY5
线程的优先级主要作用是可以获得执行机会次数多少有关,并非线程级别越高就优先执行,哪个线程先运行还是取决于CPU的调度
package _05_kongzhi_Thread;
class priority extends Thread{
priority(String name){
super(name);
}
@Override
public void run() {
for(int i=0;i<100;i++){
System.out.println(this.getName()+"---"+ i );
}
}
}
public class PriorityDemo {
public static void main(String[] args) {
priority p1 = new priority("优先级高的");
priority p2 = new priority("优先级低的");
p1.setPriority(10);
p1.start();
p2.start();
}
}
线程礼让
void yield() 没啥用,你想让,但是谁先执行还是取决于CPU的
Thread过时的方法和定时器
void resume();//取消挂起
suspend();//挂起线程
void stop();//终止线程
已经被wait和notify取代,知道就好.
Timer
package _06_Timer;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class Test {
public static void main(String[] args) {
/*
Date d = new Date(System.currentTimeMillis() + 3000);
new Timer().schedule(new TimerTask(){
@Override
public void run() {
System.out.println("hello");
}
}, d);
*/
new Timer().schedule(new TimerTask(){
@Override
public void run() {
System.out.println(new Date().toLocaleString());
}
}, 0, 1000);
}
}