一、进程
进程是一个独立运行的应用程序。比如电脑软件,qq、微信等,启动起来以后,就是一个进程
进程 需要系统进行资源分配,可以获取当前系统内存,网卡,显卡等
进程的特点:
1.独立性 各个进程之间是互相独立的,互相不影响的。
2.互斥性 每个应用程序(软件),系统为其分配一个独立的端口号。如果QQ软件端口号97,IDEL端口号也是97,系统在调97号时只能有一个运行。
写代码Demo1里的main主函数,Demo1可以看成一个应用程序,就是一个进程。
二、线程
进程是由至少一个或者多个线程组成的。线程是进程的最小基本单位。
线程的特性:
1.抢占式运行【重要】 给程序分配CPU,是按照时间片来执行,单位时间片抢占式执行。是随机抢占的。
2.资源共享 同一个进程,有多个线程。这多个线程是可以共享同一个数据的
Demo1可以看成一个进程,
一个Java程序中有两个线程:
1.main主线程
2.垃圾回收线程
三、并行和并发
并行:两个或者多个事件在 同⼀时刻 发生。
并发:两个或多个事件在 同⼀时间间隔 发生。
并行是真正意义上,同⼀时刻做多件事情,而并发在同⼀时刻只会做⼀件事件,只是可以将时间切碎,交替做多件事情。
四、创建线程的两种方式
Java虚拟机允许应用程序同时执行多个线程
1.第一种创建方式
创建线程的第一种方式:
是将一个类声明为Thread
类的子类。 这个子类应该重写Thread
类下的run
方法。 然后可以分配并启动子类的实例。
package cpm.qf.a_Thread;
//1.将一个类声明为Thread类的子类
class MyThread1 extends Thread{
//2.重写run方法
@Override
public void run() {
for(int i = 1;i<=10; i++){
System.out.println("MyThread1线程 "+i);
}
}
}
class MyThread2 extends Thread{
@Override
public void run() {
for(int i = 1; i<=10; i++){
System.out.println("MyThread2线程 "+i);
}
}
}
public class Demo3 {
public static void main(String[] args) {
//3.新建线程的实例
MyThread2 myThread2 = new MyThread2();
//4。启动线程
myThread2.start();
MyThread1 myThread1 = new MyThread1();
myThread1.start();
for(int i = 1; i<=10;i++){
System.out.println("主线程 "+i);
}
}
}
练习:新建两个线程,一个线程打印99乘法表,另外一个线程打印直角三角形
package cpm.qf.a_Thread;
class MyThread3 extends Thread{//九九乘法表
@Override
public void run() {
for(int i = 1; i<=9; i++){
for(int j = 1;j<= i; j++){
System.out.print(j+"*"+i+"="+j*i+"\t");
}
System.out.println();
}
}
}
class MyThread4 extends Thread{//打印直角三角形
@Override
public void run() {
for(int i = 1; i<=4; i++){
for(int j = 1;j<=i; j++){
System.out.print("*");
}
System.out.println();
}
}
}
public class Demo4 {
public static void main(String[] args) {
new MyThread3().start();
new MyThread4().start();
}
}
2.第二种创建方式
创建线程的第二种方式
创建一个线程,作为Runnable
接口的实现类,并实现run
方法。 然后可以分配类的实例,在创建Thread
时作为参数传递,并启动。
package cpm.qf.a_Thread;
//声明一个实现Runnable接口的类
class MyThread5 implements Runnable{
@Override
public void run() {
for(int i = 0; i<100; i++){
System.out.println("MyThread5 "+i);
}
}
}
class MyThread6 implements Runnable{
@Override
public void run() {
for(int i = 0; i<100; i++){
System.out.println("MyThread6 "+i);
}
}
}
public class Demo5 {
public static void main(String[] args) {
MyThread5 myThread5 = new MyThread5();
//在创建Thread时作为参数传递并启动
new Thread(myThread5).start();
new Thread(new MyThread6()).start();
}
}
练习:新建两个线程,一个线程打印99乘法表,另外一个线程打印直接三角形
package cpm.qf.a_xiancheng;
public class Demo7 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
for(int i = 1; i<10;i++){//九九乘法表
for(int j=1; j<=i; j++){
System.out.print(j+"*"+i+"="+j*i+"\t");
}
System.out.println();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for(int m = 1;m<5;m++){
for(int n = 1;n<=2*m-1; n++){
System.out.print("*");
}
System.out.println();
}
}
}).start();
}
}
/*
在开发中使用第二种方式,为什么?
第一种方式:继承Thread类,只能单继承
第二种方式:实现Runnable接口,一个类可以实现多个接口
*/
示例:
package cpm.qf.a_xiancheng;
class Person{
}
class Man extends Person implements Runnable{
@Override
public void run() {
}
}
class Woman extends Person implements Runnable{
@Override
public void run() {
}
}
public class Demo8 {
public static void main(String[] args) {
}
}
五、线程下的方法
1.构造方法
Thread()//分配一个新的Thread对象
Thread(Runnable target)
//分配一个新的Thread对象,第二种创建的形式
Thread(Runnable target, String name)
//分配一个新的Thread对象,并对这个线程起一个名字
2.方法
static Thread currentThread()
//返回对当前正在执行的线程对象的引用
String getName()
//返回此线程的名字
void setName(String name)
//将此线程名称改为参数name
package com.qf.mothed_Thread;
class MyThread1 implements Runnable{
@Override
public void run() {
Thread thread = Thread.currentThread();
//MyThread1默认的名字 Thread-0
System.out.println(thread.getName());
}
}
class MyThread2 implements Runnable{
@Override
public void run() {
Thread thread = Thread.currentThread();
//MyThread2默认的名字 Thread-1
System.out.println(thread.getName());
}
}
public class Demo1 {
public static void main(String[] args) {
Thread thread = Thread.currentThread();//获取当前线程对象
System.out.println(thread.getName());//获取此线程的名字 main
Thread thread1 = new Thread(new MyThread1(),"二狗");//二狗
thread1.start();
new Thread(new MyThread2()).start();//Thread-0
}
}
int getPriority();
//返回此线程的优先级
void setPriority(int newPriority)
//更改此线程的优先级
static void sleep(long millis)
//使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)
package com.qf.mothed_Thread;
class MyThread3 implements Runnable{
@Override
public void run() {
for(int i = 0;i<=10;i++){
System.out.println("优先级是1的:"+i);
}
}
}
class MyThread4 implements Runnable{
@Override
public void run() {
for(int i= 0;i<=10;i++){
System.out.println("优先级是10的:"+i);
}
}
}
public class Demo2 {
public static void main(String[] args) {
Thread thread = Thread.currentThread();//获取当前线程(main)对象的引用
System.out.println(thread.getPriority());//获取当前线程的优先级为5
Thread thread1 = new Thread(new MyThread3());
thread1.setPriority(1);
thread1.start();
Thread thread2 = new Thread(new MyThread4());
thread2.setPriority(10);
thread2.start();
}
}
这里开启两个线程,从优先级来看,优先级为10的线程应该更早执行完,但是还是抢占,结果不可预测,接下来试试为其中一个线程加上sleep()
package com.qf.mothed_Thread;
class MyThread3 implements Runnable{
@Override
public void run() {
for(int i = 0;i<=10;i++){
System.out.println("优先级是1的:"+i);
}
}
}
class MyThread4 implements Runnable{
@Override
public void run() {
/*
为什么 Thread.sleep(1000); 只能try-catche而不能throws呢?
run方法是重写的方法,重写public abstract void run();
重写有严格限定,名字,参数,返回值都不能变,限定严格
*/
try{
Thread.sleep(1000);//休眠1000毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
for(int i= 0;i<=10;i++){
System.out.println("优先级是10的:"+i);
}
}
}
public class Demo2 {
public static void main(String[] args) {
Thread thread = Thread.currentThread();//获取当前线程(main)对象的引用
System.out.println(thread.getPriority());//获取当前线程的优先级为5
Thread thread1 = new Thread(new MyThread3());
thread1.setPriority(1);
thread1.start();
Thread thread2 = new Thread(new MyThread4());
thread2.setPriority(10);
thread2.start();
}
}
这里为优先级高的线程添加sleep(),让其休眠1秒。可以看到,1秒的时间差,足以让优先级为1的线程早于优先级更高的线程(优先级为10)执行结束。
完结,撒花~