程序 = 算法 + 数据结构。程序是为了完成某种特定任务,用编程语言写的一组指令集合
进程:正在运行的一个程序
线程:进程内部的一条一条的执行路径,之前写的代码都是单线程的
多线程优点
增加用户的操作体验(你在看视频的同时可以听到声音)
提高cpu利用率
1.通过thread类创建
1.创建一个继承thread的子类
2.重写run方法,代码块为要执行的东西
3.创建对象
4.调用这个对象的start方法(从thread继承过来的)
//生成100以内的偶数
public class play{
public static void main(String[] args) {
mytest my = new mytest();
my.start();
}
}
class mytest extends Thread{
public void run() {
for(int i=0;i<100;i++)
if(i%2==0)
System.out.println(i);
}
}
*********************************************************************
常用方法:
start():启动线程,调用run方法。
run():需要重写
currentThread():静态方法,建议用Thread.调用,返回结果为当前线程
getName():获得当前线程的名字
setName():设置名字(默认名字为Thread-n),也可以才niu对象的时候用构造函数设置线程名字
isAlive():判断线程是否还活着。
yield():静态方法,暂停当前线程(释放CPU控制权),但是不阻塞,紧接着下一时间短这个线程还有可能抢到CPU控制权。也是直接在run内调用即可
join():阻塞线程(插队)。比如说在主线程内调用a.join(),那么主线程就阻塞了,直到a线程运行结束后主线程才继续开始。在司机与售票员那个问题中可以用。会抛出InterruptedException异常,需要接收一下
sleep(long time):静态方法,设置当前线程的休眠时间,单位为毫秒(千分之一秒)。会抛出InterruptedException异常,需要接收一下。直接在run方法内设置即可,如sleep(10);
设置线程的优先级:
三个常量,可以直接调用
MAX_PRIORITY:10
MIN_PRIORITY:10
NORM_PRIORITY:10
getPriority():获得优先级
setPriority(int x):设置优先级,范围为1~10,默认为5
---------------------------------------------------------------------------
stop():强制结束线程,杀死线程。(过时了,不再用了,只需要认识就好)
2.通过Runnable接口创建
1.创建一个继承Runnable的子类
2.重写run方法,代码块为要执行的东西
3.创建对象
4.将这个对象传递到Thread的构造器中,创建Thread对象
5.调用Thread对象的start方法
因为没有继承Thread类,所以说调用Thread类的时候需要用Thread.调用
public class play{
public static void main(String[] args) {
test te = new test();
Thread th = new Thread(te);
th.start();
}
}
class test implements Runnable{
@Override
public void run() {
for(int i=0;i<100;i++)
if(i%2==0)
System.out.println(i);
}
}
Thread与Runnable差别
1.一般来说使用Runnable,因为一个类只能继承一个父类,但是能继承多个接口。
2.Rannable进行线程之间共享数据比较简单,不用设置为static了。
3.Thread内部源码也继承了Runnable。
3.线程的生命周期
新建 (new出来对象),
就绪 (调用statr,等待进入CPU),
运行 (进入cpu),
阻塞 (等待IO操作),
死亡 (程序运行结束)。
4.临界资源,临界区
synchronized 加锁,设置临界区
1.synchronized(this) {处理临界资源语句,代码块}
小括号里面是锁(可以写任意对象),但是线程要共用一个锁,所以说小括号内的对象要一致,一般用this,因为this指的是同一个对象
这样只适用于继承Runnable的对象,不适合thread,应为this指的不是同一个对象
2.当方法修饰符,来修饰一个方法,只有当这个方法内全是和临界资源有关的才行
Runnable: private synchronized void show(){同步代码块} 然后可以用run调用这个,会有一个默认的this
Thread:只能同时也把这个类设置成静态的,因为this指的是不同对象
3.使用Look锁,look是一个接口,用的是里面的ReentrantLock,锁的也是当前对象,在继承Thread类内使用的话,也需要设置成静态的,避免look指向不同的对象
import java.util.concurrent.locks.ReentrantLock;
public class play{
public static void main(String[] args) {
train ta =new train();
Thread th = new Thread(ta,"线程一");
Thread th1 = new Thread(ta,"线程二");
th.start();
th1.start();
}
}
class train implements Runnable{
private int tick = 200;
private ReentrantLock look = new ReentrantLock();
public void run() {
while(true) {
try {
look.lock(); 上锁
if(tick>0) {
System.out.println(Thread.currentThread().getName()+"票号为"+tick);
tick--;
}
else
break;
}
finally {
look.unlock(); 写在finally语句内,无论如何都会解锁
}
}
}
}
Look与synchronized的差别:
1.look是手动上锁,手动解锁,synchronized是自动上锁解锁
5.死锁
临界区,临界资源应尽量少用,避免死锁
6.线程通信
只能在同步代码块内用,Look内用不成。
调用这三个方法的对象,必须是当作锁的那个对象,换成别的会报错。this的话可以不写
wait() 阻塞当前进程,并且释放手中的锁。也会报出InterruptedException异常,需要接收
notify() 唤醒之前在这个代码快内阻塞的进程,优先唤醒优先级高的,只唤醒一个
notifyAll() 唤醒所有阻塞的进程,优先级高的先被唤醒并执行,唤醒多个
三个方法是在object类内定义的
wait与sleep的异同:
同:都可以阻塞进程。
异:sleep在哪都可以用,wait只能在同步代码块内用
sleep不会释放锁,wait会
7.使用Callable接口创建
这里需要重写call方法,有返回值,可以抛异常,支持泛型
1.创建一个实现Callable的实现类(需要导入)
2.实现call方法
3.在主线程中创建这个类的对象
4.将创建的这个对象传递到FutureTask构造器中(需要导入)
5.创建Thread对象,调用start方法
6.利用新建的FutureTask对象,可以获得返回值
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class play{
public static void main(String[] args) {
test te = new test();
FutureTask fu = new FutureTask(te);
new Thread(fu).start();
try {
Object oj = fu.get(); //获取call方法的返回值
System.out.println(oj);
}
catch(Exception e){
e.printStackTrace();
}
}
}
class test implements Callable{
@Override
public Object call() throws Exception {
int sum=0;
for(int i=0;i<=100;i++)
if(i%2==0) {
System.out.println(i);
sum += i;
}
return sum;
}
}
8.使用线程池创建
Executors
好处:
1.减少了创建新线程的时间
2.降低资源消耗
3.便于线程管理
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class play{
public static void main(String[] args) {
ExecutorService st = Executors.newFixedThreadPool(10);
st.execute(new test()); 适用于Runnable对象
//st.submit(task) 适用于Callable对象,有返回值,接收方法和前面一样
st.shutdown(); 关闭线程池
}
}
class test implements Runnable{
@Override
public void run() {
for(int i=0;i<100;i++)
if(i%2==0)
System.out.println(i);
}
}
生产者消费者代码
写的不好,别打我
public class play{
public static void main(String[] args) {
clerk cl = new clerk();
productor pd = new productor(cl);
customer cu = new customer(cl);
Thread th1 = new Thread(pd , "生产者");
Thread th2 = new Thread(cu , "消费者");
th1.start();
th2.start();
}
}
class clerk{
private int num = 20;
public void setNum(int num) {
this.num = num;
}
public int getNum() {
return num;
}
}
class productor implements Runnable{
private clerk ple;
public productor(clerk ple) {
this.ple = ple;
}
@Override
public void run() {
while(true) {
synchronized(ple) {
System.out.println("开始生产商品.......");
if(ple.getNum()>0) {
ple.setNum(ple.getNum()-1);
System.out.println("剩余商品"+(20-ple.getNum()));
ple.notify();
}
else
try {
System.out.println("没有空余位置了,暂停生产");
ple.wait();
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
class customer implements Runnable{
private clerk ple;
public customer(clerk ple) {
this.ple = ple;
}
@Override
public void run() {
while(true) {
synchronized(ple) {
System.out.println("开始购买商品.......");
if(ple.getNum()<20) {
ple.setNum(ple.getNum()+1);
System.out.println("剩余商品"+(20-ple.getNum()));
ple.notify();
}
else
try {
System.out.println("没有产品了,暂停购买");
ple.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
3万+

被折叠的 条评论
为什么被折叠?



