1.程序:未解决某种问题,使用计算机语言编写的一些列指令(代码)的集合
2.进程:正在运行的程序(被加载到内存中),是操作系统进行资源分配的最小单位
3.线程:进程可以进一步细化为线程(比进程更小)且线程是隶属于进程的,是操作系统执行的最小的执行单元 也是cpu
进行任务调度的最小单位
QQ
也是一个进程,操作系统就会为这个进程分配资源 一个聊天窗口就是一个线程,线程隶属于进程tips:早期是没有线程的,是以进程为单位执行的,进程的单位比较大,当一个进程运行时,其他进程就不能执行了,所以后来,将进程中的多个任务细化为线程,cpu
的执行单位,也是从进程进化为更小的线程
总结
java
中mian方法
就是用来启动主线程在Java
中Thread
表示线程,提供了许多的方法,来对线程的控制,可以通过继承Thread
类来实现线程
Thread常用方法
Thread.currentThread();
run();
start();
Java
线程setName(String name);
(String)getName();
getPriority();
setPriority();
sleep(long ms);
join();
Thread构造方法
new Thread(Runnable runnable);
new Thread(Runnable runnable,String name);
使用上面方法进行实例
线程1
public class MyThread extends Thread{
//重写run方法,在run中执行我们要执行的方法
@Override
public void run() {
for(int i=0;i<10000;i++){
System.out.println("循环main"+i);
}
}
}
线程2
public class MyThread2 extends Thread {
@Override
public void run() {
for(int i=0;i<10000;i++){
System.out.println("循环main2"+i);
}
}
}
public class 线程 {
public static void main(String[] args) {
for(int i=0;i<10000;i++){
System.out.println("循环1 "+i);
}
for(int i=0;i<10000;i++){
System.out.println("循环2 "+i);
}
for(int i=0;i<10000;i++){
System.out.println("循环3 "+i);
}
for(int i=0;i<10000;i++){
System.out.println("循环4 "+i);
}
/*
这样不管怎么执行都是单线程,从上到下依次执行,
所以如果想在java程序中有几件不想管的事件同时执行
可以在java中创建线程,把一些需要执行的任务放在线程中执行,
这样就拥有让cup执行的权利
*/
MyThread myThread = new MyThread();
//调用start方法让程序多线程进行,重写run方法但不能调用run,不然只是普通方法的调用,依然是单线程
myThread.start();
MyThread2 myThread2 = new MyThread2();
myThread2.start();
}
}
观察结果 可知 MyThread
与MyThread2
是同时进行的
Java中我们也可以实现Runnable接口来进行对线程的实现
思路.
创建一个类 实现Runnable接口
重写run方法
在main函数使用Thread构造方法
传入Runnable对象
public class MyTask implements Runnable{
@Override
public void run() {
for(int i=0;i<10;i++){
System.out.println("啊");
}
}
}
MyTask myTask = new MyTask();
//创建一个线程
Thread thread = new Thread(myTask);
Java中也可以实现Callable接口 重写 call()方法 来对线程的实现
思路.
call()
方法 call()
方法有返回值 可以抛出异常,还可以处理不同类型Thread
构造方法来创建一个线程从线程到销毁期间经历五个状态
setDaemon();
如果一个**线程
是守护线程**,那么它会等待java
中其他线程任务结束后,自动终止jvm
中的垃圾回收机制,就是一个守护线程在一个应用程序中,存在多个线程,不同线程可以并行的执行任务
分析
对于内存资源与CPU资源我们可以通过不断增加内存来解决
对于线程安全问题 我们则需要对 线程进行加锁
synchronized 修饰代码块需要加一个同步对象 synchronized(同步对象)
同步对象要求
java
类中任何类对象.修饰方法
修饰代码块例子
package day17;
public class PrintNums implements Runnable{
//实现线程的交替打印
int num=100;
Object object = new Object();
@Override
public void run() {
while(true){
synchronized (object){
object.notify();//唤醒线程
if(num==0){
break;
}
System.out.println(Thread.currentThread().getName()+"."+num+".");
num--;
try {
object.wait();//线程等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
package day17;
public class TestPrintNums {
public static void main(String[] args) {
PrintNums printNums = new PrintNums();
Thread t1 = new Thread(printNums,"1");
Thread t2 = new Thread(printNums,"2");
Thread t3 = new Thread(printNums,"3");
t1.start();
t2.start();
t3.start();
}
}
于是我们实现了交替打印 每次只能进入一个线程
修饰方法(同步对象会有默认的)
synchronized
如果修饰的是非静态方法,锁的对象是this
synchronized
如果修饰的是静态方法,锁的对象是类的Class对象
,一个类只有 一个对象
如果是非静态方法,那么同步对象是this(如果是非静态对象,我们可以使用Runnable创建线程方法)
如果是静态方法,所得对象是当前类的Class对象
当前类的Class对象
:一个类加载到内存后会为这个类创建唯一的Class类的对象
Class类实例表示正在运行的Java应用程序中的类和接口
修饰静态方法
public class SellTicket extends Thread {
static int counts = 10;//10张票
static Object object = new Object();
@Override
public void run() {
while (counts > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
sellTicket();
}
}
public static synchronized void sellTicket() {
if(counts>0){
System.out.println(Thread.currentThread().getName()+"买了"+counts+"张票");
--counts;
}
}
}
public class Test {
public static void main(String[] args) {
SellTicket t1 = new SellTicket();
t1.setName("窗口1");
SellTicket t2 = new SellTicket();
t2.setName("窗口2");
t1.start();
t2.start();
}
}
修饰非静态方法
public class SellTickets2 implements Runnable{
int t=20;//票数
@Override
public void run() {
while(t>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
sell2();
}
}
public synchronized void sell2(){
if(t>0){
System.out.println(Thread.currentThread().getName()+"买了"+t+"张票");
--t;
}
}
}
public class Test2 {
public static void main(String[] args) {
SellTickets2 sellTickets2 = new SellTickets2();
Thread t1 = new Thread(sellTickets2,"窗口1");
Thread t2 = new Thread(sellTickets2,"窗口2");
t1.start();
t2.start();
}
}
ReentrantLock r = new ReentrantLock();//创建 ReentrantLock对象
r.lock();<---------|//加锁
|
............. |------被锁部分(一次只进去一个线程)
|
r.unlock();<-------|//解锁
tips:r.unlock();
最好写在finally{};代码块中,保证发生异常时,也能够解锁;
synchronized
是一个关键字,ReentrantLock
是一个类
synchronized
修饰代码块和方法,ReentrantLock
只能修饰代码块
synchronized
可以隐式的加锁和释放锁,运行出现异常可以自动释放锁
ReentrantLock
需要手动加锁和释放锁,建议在finally
代码中释放锁
wait ``notify
notifyAll
wait()
;方法使当前线程进入等待状态,直到另一个线程调用该对象的notify()
或notifyAll()
方法来唤醒它
notify();
方法唤醒在该对象上调用wait()
方法进入等待状态的一个线程,如果有多个线程在等待,则只会唤醒其中一个线程。
notifyAll();
方法唤醒在该对象上调用wait()
方法进入等待状态的所有线程。
tips:1.都是Object类中定义的方法
2.三个方法必须在同步代码块中使用
3.这三个方法必须通过为锁的对象调用