java——线程学习笔记
1、线程的理解:
(1)线程的使用:
线程的学习难点并不在于如何创建、开启一个线程,而是应该何时创建,线程如何同步,使得程序能够运行得到预期的结果。
比如文字处理程序 你可以设置每隔多长时间 输入的内容可以自动的保存 而这个保存操作并不需要你的介入 而是使用一个线程专门负责这个操作,在这个程序中至少得有两个线程 一个便是主线程 用来捕获你从键盘输入的内容 而另一个线程则负责定时保存输入的内容。
在后面的socket的学习中也用到了多线程:
(2)线程的执行:
只有在多处理器的机器上, 多线程才会被真正的同时运行,在单处理机上多线程是占用分配的时间片来运行,因为处理机的速度比较快 使得我们看起来它像是在同时运行,也就是我们操作系统中所说的并发和并行的概念。
2、线程的创建:
方法一:定义线程实现Runnable接口
方法二:定义一个Thread的子类并重写run方法
代码实现
public class MyThread implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++) {
System.out.println("myThread"+i);
}
}
}
public class MyThread1 extends Thread {
public void run() {
for(int i=0;i<10;i++) {
System.out.println("MyThread"+i);
}
}
}
public class MainTread {
public static void main(String[] args) {
Runnable r1=new MyThread();
//r1.run();这样只是执行了线程体,而不是开辟出类一个线程与主线程同时运行
//这样就开辟出来一个新的线程 Thread(Runnable target)
Thread t=new Thread(r1);//要启动一个新的线程就必须new一个Thread对象出来
t.start();//线程启动调用start方法 线程执行默认运行的run()方法
/*
方法二:
MyThread1 mt=new MyThread1();
mt.start();
*/
for(int i=0;i<10;i++){
System.out.println("mainthod:"+i);
}
}
}
3、线程的管理
(1)join()
等待该线程终止,在当前线程中调用另一个线程的jion方法,则当前线程转入阻塞状态,直到另一个线程运行结束后,当前线程才会由阻塞状态转为就绪状态
代码实现:
public class MainThread {
public static void main(String[] args) {
MyThread mt=new MyThread();
MyThread1 mt1=new MyThread1();
/*
* Thread(Runnable target)分配新的target对象
* */
Thread tr1=new Thread(mt1);
Thread tr=new Thread(mt);
tr1.start();
tr.start();
try {
tr1.join();
tr.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(int i=0;i<50;i++) {
System.out.println("MainThread"+i);
}
//tr1与tr线程若放在后面启动的话 则是等主线程结束后才会启动执行
/*
* 那么此处我们就开始思考了 线程的并发执行是无序的 我们该如何使得线程能够按照某种顺序执行呢?
* 即采用jion方法了
* */
//tr1.start();
//tr.start();
}
此处代码运行的结果是 待tr tr1线程运行结束后 主线程才会开始运行
(2)yield和sleep
yield和sleep(0)实现的效果一样,因此我们可以发现它俩的区别是sleep可以规定该线程多长时间内不可以抢占处理机,而yield()不可以,它意味着该线程放弃处理机后立马可以参加抢占处理机
代码实现:
public class MyThread implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<50;i++) {
/*
* 每循环一次 该线程让出了处理机 即处理机重新选择分配给一个线程 进行运行 仍有可能分配给原来的线程
* */
Thread.yield();
System.out.println("MyThread"+i);
}
}
}
public class MyThread implements Runnable {
@Override
public void run() {
try {
Thread.sleep(1000);//该线程休眠 5秒
} catch (InterruptedException e) {
e.printStackTrace();
}
for(int i=0;i<50;i++) {
System.out.println("MyThread"+i);
}
}
}
(3)设置线程的优先级
需要注意的是Java中
优先级高的线程只能有机会优先被执行 而不会绝对被优先执行
代码实现:
public class MainThread {
/*
* 线程优先级设置测试
* */
public static void main(String[] args) {
MyThread1 mt1=new MyThread1();
MyThread2 mt2=new MyThread2();
Thread tr1=new Thread(mt1);
Thread tr2=new Thread(mt2);
int p1 = tr1.getPriority();
int p2 = tr2.getPriority();
System.out.println(p1+" "+p2);//线程的默认优先级为5
//设置线程的优先级
tr1.setPriority(10);
tr2.setPriority(7);
tr1.start();
tr2.start();
for(int i=0;i<50;i++) {
System.out.println("MainThread "+i);
}
}
}
(4)wait(),notify()与 synchronized
需要先明白以下几个问题:
1、如何使用?
(1)obj.wait()(等待) 与 obj.notify()(唤醒) 必须要与synchronized(obj)方法一起使用
(2)wait()必须在synchronized代码块中,它使得当前线程等待,直到其它线程调用此对象的notify()或notifyAll()方法,即其它线程唤醒自己。
(3)notify()方法可不可以自己唤醒自己? 答案当然是NO,notify()唤醒的是在等待队列中的线程,自己就没有在等待队列,需要注意的是notify()唤醒的是等待队列中的随机一个线程, notifyAll()可将等待队列中的所有的线程全部唤醒
2、wait()与sleep的区别 。
sleep是线程的方法 wait是object的方法 sleep释放的CPU的抢占权 wait()将CPU的抢占权跟锁全部都释放
3、为什么要使用 synchronized?
多线程操作同一个对象的时候要加锁,不加锁的话会导致程序的执行无可再现性,每次的运行结果都不相同。
说了这么一大堆,比较抽象,使用线程模拟生产者消费者问题会加深理解 。
线程模拟生产者消费者问题
上一篇: OPPOFindX5Pro天玑版对比OPPOFindX5哪个值得买
下一篇: 初一吃什么