脚本宝典收集整理的这篇文章主要介绍了Java线程(基础),脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
1.单线程:同一个时刻,只允许执行一个线程 2.多线程:同一个时刻,可以执行多个线程,比如:一个QQ进程,可以同时打开多个聊天窗口,一个迅雷进程,可以同时下载多个文件
在java中线程来使用有两种方法。 1.继承Thread类,重写run方法 2.实现Runnable接口,重写run方法
当main线程通过start()方法启动一个子线程Thread-0,并不代表主线程会阻塞,它会继续执行,并且与子线程交替执行 主线程结束但是任有子线程不会造成应用程序的结束 主线程可以开多个子线程,子线程也能开新的子线程
创建一个进程每隔一秒输出内容,输出8次后停止
package Threaduse;
//演示通过继承Thread 类创建线程
public class test {
public static void main(String[] args) {
//创建Cat对象,可以当做线程使用
cat cat = new cat();
cat.start();//启动线程-> 最终会执行cat的run方法
}
}
//1. 当一个类继承了 Thread 类, 该类就可以当做线程使用
//2. 我们会重写 run方法,写上自己的业务代码
//3. run Thread 类 实现了 Runnable 接口的run方法
/*
@override
public void run() {
if (target != null) {
target.run();
}
}
*/
class cat extends Thread{
//重写run()方法
@Override
public void run() {//在这里写上自己要实现的业务逻辑
suPEr.run();
int times=0;
while(@H_543_304@true){
System.out.PRintln("熊猫烧香"+times++);
//休眠一秒钟(一毫秒为单位),抛出异常ctrl+alt+t
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(times==8){
break;
}
}
}
}
cat.run()//是一个普通方法,由主线程直接调用run()方法,无法实现线程 cat.start()//启动线程,最终会执行cat.run()方法
start()方法源码解读: run()方法何时执行取决于CPU说明
深入内容到之后再讲,先介绍怎么实现
package Threaduse;
public class Thread02 {
public static void main(String[] args) {
//底层使用了代理模式(一种设计模式)
Dog dog = new Dog();
Thread thread = new Thread(dog);
thread.start();
}
}
class Dog implements Runnable {
@Override
public void run() {
//设置自己想设计的逻辑
int num=0;
while(true){
System.out.println("熊猫烧香"+(++num)+Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(num==8){
break;
}
}
}
}
package Threaduse;
public class SellTicketSystem {
public static void main(String[] args) {
//使用Thread实现线程
// SellTicket01 sellTicket01 = new SellTicket01();
// SellTicket01 sellTicket02 = new SellTicket01();
// SellTicket01 sellTicket03 = new SellTicket01();
// sellTicket01.start();
// sellTicket02.start();
// sellTicket03.start();
//使用Runnable接口
SellTicket02 sellTicket02 = new SellTicket02();
Thread thread = new Thread(sellTicket02);
Thread thread2 = new Thread(sellTicket02);
Thread thread3 = new Thread(sellTicket02);
thread.start();
thread2.start();
thread3.start();
}
}
class SellTicket01 extends Thread {
private static int nums=100;
@Override
public void run() {
while(true){
if(nums<=0){
System.out.println("票卖完了");
break;
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("售票口"+Thread.currentThread().getName()+"卖出一张票"+"剩余票数"+(nums--));
}
}
}
class SellTicket02 implements Runnable {
private int nums=100;//这里不用定义static,因为始终使用的是同一个SellTicket02生成的对象
@Override
public void run() {
while(true){
if(nums<=0){
System.out.println("票卖完了");
break;
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("售票口"+Thread.currentThread().getName()+"卖出一张票"+"剩余票数"+(nums--));
}
}
}
●基本说明 1.当线程完成任务后,会自动退出。 2.还可以通过使用变量来控制run方法退出的方式停止线程,即通知方式
package Threaduse;
public class Stopthread {
public static void main(String[] args) throws InterruptedException {
//需求:启动一个线程t,要求在main线程中去停止线程t,请编程实现.
如果希望main线程去控制t1 线程的终止,必须可以修改 loop
// 让t1 退出run方法,从而终止t1线程->通知方式
让主线程休眠10秒,再通知和线程退出
T t = new T();
t.start();
Thread.sleep(10000);
t.setLoop(false);
}
}
class T extends Thread {
private boolean loop=true;
@Override
public void run() {
while(loop){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程在运行");
}
}
public void setLoop(boolean b){
loop=b;
}
}
1.setName /设置线程名称,使之与参数name相同 2.getName//返回该线程的名称 3. start//使该线程开始执行;Java虚拟机底层调用该线程的start()方法 4. run//调用线程对象run方法; 5. setPriorITy //更改线程的优先级 6.getPriority//获取线程的优先级 7.sleep//在指定的毫秒数内让当前正在执行的线程休眠(暂停执行) 8. interrupt //中断线程,但没有结束线程,所以一般用于中断休眠的线程
线程的优先级范围: public static final int MIN_PRIORITY=1; public static final int NORM_PRIORITY=5; public static final int MAX_PRIORITY=10;
package Threaduse;
import javax.crypto.spec.PSource;
public class ThreadMethod {
public static void main(String[] args) throws InterruptedException {
//利用主线程设置子线程名,并中断正在休眠的线程
Z z = new Z();
z.setName("张李浩");//设置线程名
z.setPriority(Thread.MIN_PRIORITY);
z.start();
//主线程在输出5个i后,interrupt子线程
for(int i=0;i<5;i++){
Thread.sleep(1000);
System.out.println(i);
}
z.interrupt();
}
}
class Z extends Thread {
@Override
public void run() {
//先输出,休眠50秒,interrupt,然后再输出
while(true){
int nums=0;
for(int i=0;i<10;i++){
System.out.println("线程"+Thread.currentThread().getName()+"正在运行"+(++nums));
}
try {
System.out.println("线程正在休眠");
Thread.sleep(20000);
} catch (InterruptedException e) {
System.out.println("线程被打断了");
}
}
}
}
yield()线程礼让,假如CPU充足则不一定成功 join()线程插队
package Threaduse;
public class ThreadMethodExercise {
public static void main(String[] args) throws InterruptedException {
person person = new person();
Thread thread = new Thread(person);
//主线程每个一秒,输出hi,共10次
for(int i=1;i<=10;i++){
Thread.sleep(1000);
System.out.println("hi"+i);
if(i==5){
//启动子线程,让其执行完再运行主线程
thread.start();
thread.join();
}
}
System.out.println("主线程结束");
}
}
class person implements Runnable {
@Override
public void run() {
while(true){
for(int i=1;i<=10;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("hello"+i);
}
System.out.println("子线程结束");
break;
}
}
}
1.用户线程:也叫工作线程,当线程的任务执行完或通知方式结束 2守护线程:一般是为工作线程服务的,当所有的用户线程结束,守护线程自动结束 3.常见的守护线程:垃圾回收机制
守护线程当所以用户现场结束,守护线程也自动结束 mydaemoThread.setDaemo(true);//设为守护线程
package com.hspedu.method;
/**
* @author 韩顺平
* @version 1.0
*/
public class ThreadMethod03 {
public static void main(String[] args) throws InterruptedException {
MyDaemonThread myDaemonThread = new MyDaemonThread();
//如果我们希望当main线程结束后,子线程自动结束
//,只需将子线程设为守护线程即可
myDaemonThread.setDaemon(true);
myDaemonThread.start();
for( int i = 1; i <= 10; i++) {//main线程
System.out.println("宝强在辛苦的工作...");
Thread.sleep(1000);
}
}
}
class MyDaemonThread extends Thread {
public void run() {
for (; ; ) {//无限循环
try {
Thread.sleep(1000);//休眠1000毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("马蓉和宋喆快乐聊天,哈哈哈~~~");
}
}
}
细分7种,总的来说6种,都对 线程状态。线程可以处于以下6种状态之一: NEW 尚未的线程处于此状态。 RUNNABLE(RUNNABLE状态可以细分为Ready和Running两种状态------>七种) 在Java虚拟机中执行的线程处于此状态。 BLOCKED 被阻塞等待监视器锁定的线程处于此状态。 WAITING 正在等待另一个线程执行特定动作的线程处于此状态。 TIMED_WAITING 正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。 TERMINATED 已退出的线程处于此状态。
1.在多线程编程,一些敏感数据不允许被多个线程同时访问,此时就使用同步访问技术, 保证数据在任何同一时刻,最多有一个线程访问,以保证数据的完整性。 2.也可以这里理解:线程同步,即当有一个线程在对内存进行操作时, 其他线程都不可以对这个内存地址进行操作,直到该线程完成操作,其他线程才能对该内存地址进行操作.
1.同步代码块 synchronized(对象){//得到对象的锁,才能操作同步代码 //需要被同步代码; } 2. synchronized还可以放在方法声明中,表示整个方法-为同步方法 public synchronized void m (String name){ //需要被同步的代码 }
class SellTicket03 implements Runnable {
private int ticketNum = 100;//让多个线程共享 ticketNum
private boolean loop = true;//控制run方法变量
Object object=new Object();
//同步方法(静态的)的锁为当前类本身
//老韩解读
//1. public synchronized static void m1() {} 锁是加在 SellTicket03.class
//2. 如果在静态方法中,实现一个同步代码块.
/*
synchronized (SellTicket03.class) {
System.out.println(";m2");
}
*/
public synchronized static void m1() {
}
public static void m2() {
synchronized (SellTicket03.class) {
System.out.println("m2");
}
}
//老韩说明
//1. public synchronized void sell() {} 就是一个同步方法
//2. 这时锁在 this对象
//3. 也可以在代码块上写 synchronize ,同步代码块, 互斥锁还是在this对象
public void sell() { //同步方法, 在同一时刻, 只能有一个线程来执行sell方法
synchronized (/*this*/ object) {
if (ticketNum <= 0) {
System.out.println("售票结束...");
loop = false;
return;
}
//休眠50毫秒, 模拟
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票"
+ " 剩余票数=" + (--ticketNum));//1 - 0 - -1 - -2
}
}
@Override
public void run() {
while (loop) {
sell();//sell方法是一共同步方法
}
}
}
class SellTicket01 extends Thread {
private static int nums = 1000;
private boolean loop=true;
public synchronized void sell() {
if (nums <= 0) {
System.out.println("票卖完了");
loop=false;
return;
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("售票口" + Thread.currentThread().getName() + "卖出一张票" + "剩余票数" + (nums--));
}
@Override
public void run() {
while (loop) {
sell();
}
}
}
1.Java语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。 2.每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。 3.关键字synchronized来与对象的互斥锁联系。当某个对象用synchronized修饰时,表明该对象在任一时刻只能由一个线程访问 4.同步的局限性:导致程序的执行效率要降低 5.同步方法((非静态的)的锁可以是this,也可以是其他对象(要求是同一个对象) 6.同步方法(静态的)的锁为当前类本身。
1.同步方法如果没有使用static修饰:默认锁对象为this 2.如果方法使用static修饰,默认锁对象:当前类.class(static修饰没法用this) 3.实现的落地步骤: ·需要先分析上锁的代码 选择同步代码块或同步方法 要求多个线程的锁对象为同一个即可!
多个线程都占用了对方的锁资源,但不肯相让,导致了死锁,在编程是一定要避免死锁的发生.
public class DeadLock_ {
public static void main(String[] args) {
//模拟死锁现象
DeadLocKDEmo A = new DeadLockDemo(true);
A.setName("A线程");
DeadLockDemo B = new DeadLockDemo(false);
B.setName("B线程");
A.start();
B.start();
}
}
//线程
class DeadLockDemo extends Thread {
static Object o1 = new Object();// 保证多线程,共享一个对象,这里使用static
static Object o2 = new Object();
boolean flag;
public DeadLockDemo(boolean flag) {//构造器
this.flag = flag;
}
@Override
public void run() {
//下面业务逻辑的分析
//1. 如果flag 为 T, 线程A 就会先得到/持有 o1 对象锁, 然后尝试去获取 o2 对象锁
//2. 如果线程A 得不到 o2 对象锁,就会Blocked
//3. 如果flag 为 F, 线程B 就会先得到/持有 o2 对象锁, 然后尝试去获取 o1 对象锁
//4. 如果线程B 得不到 o1 对象锁,就会Blocked
if (flag) {
synchronized (o1) {//对象互斥锁, 下面就是同步代码
System.out.println(Thread.currentThread().getName() + " 进入1");
synchronized (o2) { // 这里获得li对象的监视权
System.out.println(Thread.currentThread().getName() + " 进入2");
}
}
} else {
synchronized (o2) {
System.out.println(Thread.currentThread().getName() + " 进入3");
synchronized (o1) { // 这里获得li对象的监视权
System.out.println(Thread.currentThread().getName() + " 进入4");
}
}
}
}
}
package Threaduse.HomeWork;
import java.util.Locale;
import java.util.Scanner;
//(1)在main方法中启动两个线程
//(2)第1个线程循环随机打印100以内的整数
//(3)直到第2个线程从键盘读取了“Q”命令。
public class Homework01 {
public static void main(String[] args) {
A a = new A();
B b = new B(a);
a.start();
b.start();
}
}
class A extends Thread {
private boolean loop=true;
public void setLoop(boolean b){
loop=b;
}
@Override
public void run() {
//随机打印100以内的整数
while(loop){
System.out.println((int)(Math.random()*100+1));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("线程A结束");
}
}
class B extends Thread {
private A a;
Scanner scanner = new Scanner(System.in);
public B(A a){
this.a=a;
}
@Override
public void run() {
//接收键盘输入,当接受到"Q"后将loop=false;打断线程1
while(true){
char s=scanner.next().charAt(0);
if(s=='Q') {
a.setLoop(false);
System.out.println("线程B结束");
break;
}
}
}
}
package Threaduse.HomeWork;
public class Homework02 {
public static void main(String[] args) {
user user1 = new user();
Thread thread1= new Thread(user1);
Thread thread2 = new Thread(user1);
thread1.setName("用户1");
thread2.setName("用户2");
thread1.start();
thread2.start();
}
}
class user implements Runnable{
private int money=10000;
public void put(){
while (true){
synchronized (this) {
//不断从卡里取钱,每次取1000
if (money < 1000) {
System.out.println("卡里余额不足");
break;
}
money -= 1000;
System.out.println(Thread.currentThread().getName() + "正在取钱剩余余额" + (money));
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void run() {
put();
}
}
以上是脚本宝典为你收集整理的Java线程(基础)全部内容,希望文章能够帮你解决Java线程(基础)所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。